diff options
Diffstat (limited to 'stoc/source')
117 files changed, 36863 insertions, 0 deletions
diff --git a/stoc/source/bootstrap/bootstrap.xml b/stoc/source/bootstrap/bootstrap.xml new file mode 100644 index 000000000000..3a90bbdccf71 --- /dev/null +++ b/stoc/source/bootstrap/bootstrap.xml @@ -0,0 +1,358 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + <module-name> bootstrap.uno </module-name> + <component-description> + <author> Juergen Schmidt </author> + <name> com.sun.star.comp.stoc.DLLComponentLoader </name> + <description> + This component provides a mechanism to load an external compoment implemented as + a shared library. +</description> + <loader-name> com.sun.star.loader.SharedLibrary </loader-name> + <language> c++ </language> + <status value="final"/> + <supported-service> com.sun.star.loader.SharedLibrary </supported-service> + <type> com.sun.star.util.XMacroExpander </type> + <type> com.sun.star.loader.XImplementationLoader </type> + <type> com.sun.star.lang.IllegalArgumentException </type> + <type> com.sun.star.lang.XInitialization </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.beans.XPropertySet </type> + <type> com.sun.star.container.XSet </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.uno.XComponentContext </type> + <type> com.sun.star.lang.XSingleComponentFactory </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.uno.TypeClass </type> + <type> com.sun.star.uno.DeploymentException </type> + </component-description> + <component-description> + <author> Juergen Schmidt </author> + <name> com.sun.star.comp.stoc.NestedRegistry </name> + <description> + This component provides access to a simple hierachical registry. The registry based on + two registry file. +</description> + <loader-name> com.sun.star.loader.SharedLibrary </loader-name> + <language> c++ </language> + <status value="final"/> + <supported-service> com.sun.star.registry.NestedRegistry </supported-service> + <reference-docu xlink:href="http://www.sun.com" xlink:type="simple"/> + <service-dependency> com.sun.star.registry.SimpleRegistry </service-dependency> + <type> com.sun.star.lang.XInitialization </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.registry.XSimpleRegistry </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.lang.XSingleComponentFactory </type> + <type> com.sun.star.uno.XComponentContext </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.uno.TypeClass </type> + <type> com.sun.star.container.XEnumerationAccess </type> + </component-description> + <component-description> + <author> Juergen Schmidt </author> + <name> com.sun.star.comp.stoc.ImplementationRegistration </name> + <description> + This component provides a mechanism to register or deregister an external component + to the current uno environment or better to the current service manager. +</description> + <loader-name> com.sun.star.loader.SharedLibrary </loader-name> + <language> c++ </language> + <status value="final"/> + <supported-service> com.sun.star.registry.ImplementationRegistration </supported-service> + <service-dependency> com.sun.star.registry.SimpleRegistry </service-dependency> + <service-dependency> com.sun.star.loader.SharedLibrary </service-dependency> + <service-dependency> com.sun.star.loader.Java </service-dependency> + <type> com.sun.star.loader.XImplementationLoader </type> + <type> com.sun.star.lang.XInitialization </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XSingleComponentFactory </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.registry.XSimpleRegistry </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.registry.XImplementationRegistration2 </type> + <type> com.sun.star.beans.XPropertySet </type> + <type> com.sun.star.container.XSet </type> + <type> com.sun.star.container.XHierarchicalNameAccess </type> + <type> com.sun.star.reflection.XServiceTypeDescription </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.uno.TypeClass </type> + <type> com.sun.star.uno.XComponentContext </type> + </component-description> + <component-description> + <author> Daniel Boelzle </author> + <name> com.sun.star.comp.stoc.RegistryTypeDescriptionProvider </name> + <description> +This provider service supports the XHierarchicalNameAccess interface to read type descriptions +and constants from a registry source. +</description> + <loader-name> com.sun.star.loader.SharedLibrary </loader-name> + <language> C++ </language> + <status value="final"/> + <supported-service> com.sun.star.reflection.TypeDescriptionProvider </supported-service> + <service-dependency>com.sun.star.reflection.TypeDescriptionManager</service-dependency> + <type> com.sun.star.reflection.XTypeDescription </type> + <type> com.sun.star.reflection.XConstantsTypeDescription </type> + <type> com.sun.star.reflection.XEnumTypeDescription </type> + <type> com.sun.star.reflection.XIndirectTypeDescription </type> + <type> com.sun.star.reflection.XInterfaceMemberTypeDescription </type> + <type> com.sun.star.reflection.XInterfaceAttributeTypeDescription2 </type> + <type> com.sun.star.reflection.XMethodParameter </type> + <type> com.sun.star.reflection.XModuleTypeDescription </type> + <type> com.sun.star.reflection.XInterfaceMethodTypeDescription </type> + <type> com.sun.star.reflection.XInterfaceTypeDescription </type> + <type> com.sun.star.reflection.XInterfaceTypeDescription2 </type> + <type> com.sun.star.reflection.XCompoundTypeDescription </type> + <type> com.sun.star.reflection.XServiceConstructorDescription </type> + <type> com.sun.star.reflection.XServiceTypeDescription </type> + <type> com.sun.star.reflection.XServiceTypeDescription2 </type> + <type> com.sun.star.reflection.XSingletonTypeDescription2 </type> + <type> com.sun.star.reflection.XTypeDescriptionEnumerationAccess </type> + <type> com.sun.star.reflection.XParameter </type> + <type> com.sun.star.reflection.XPublished</type> + <type> com.sun.star.reflection.XStructTypeDescription</type> + <type> com.sun.star.lang.DisposedException </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleComponentFactory </type> + <type> com.sun.star.lang.XMultiComponentFactory </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XInitialization </type> + <type> com.sun.star.registry.XSimpleRegistry </type> + <type> com.sun.star.beans.PropertyAttribute </type> + <type> com.sun.star.beans.XPropertySet </type> + <type> com.sun.star.container.NoSuchElementException </type> + <type> com.sun.star.container.XHierarchicalNameAccess </type> + <type> com.sun.star.container.XSet </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.uno.XComponentContext </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.uno.XInterface </type> + <type> com.sun.star.uno.TypeClass </type> + <type> com.sun.star.uno.RuntimeException </type> + </component-description> + <component-description> + <author>boelzle@sun.com</author> + <name>com.sun.star.security.comp.stoc.AccessController</name> +<description> +This service is an implementation of the com.sun.star.security.AccessController service. +</description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>C++</language> + <status value="under construction"/> + <supported-service>com.sun.star.security.AccessController</supported-service> + <service-dependency> unknown, because of used policy </service-dependency> + <type>com.sun.star.security.XAccessController</type> + <type>com.sun.star.security.XPolicy</type> + <type>com.sun.star.security.RuntimePermission</type> + <type>com.sun.star.security.AllPermission</type> + <type>com.sun.star.io.FilePermission</type> + <type>com.sun.star.connection.SocketPermission</type> + <type>com.sun.star.registry.XRegistryKey</type> + <type>com.sun.star.lang.DisposedException</type> + <type>com.sun.star.lang.XTypeProvider</type> + <type>com.sun.star.lang.XComponent</type> + <type>com.sun.star.lang.XServiceInfo</type> + <type>com.sun.star.lang.XSingleComponentFactory</type> + <type>com.sun.star.lang.XSingleServiceFactory</type> + <type>com.sun.star.lang.XMultiComponentFactory</type> + <type>com.sun.star.lang.XMultiServiceFactory</type> + <type>com.sun.star.lang.XInitialization</type> + <type>com.sun.star.uno.XWeak</type> + <type>com.sun.star.uno.XAggregation</type> + <type>com.sun.star.uno.DeploymentException</type> + <type>com.sun.star.uno.XCurrentContext</type> + <type>com.sun.star.uno.XComponentContext</type> + <type>com.sun.star.uno.TypeClass</type> + </component-description> + <component-description> + <author>boelzle@sun.com</author> + <name>com.sun.star.security.comp.stoc.FilePolicy</name> +<description> +This service is an implementation of the com.sun.star.security.Policy service. +</description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>C++</language> + <status value="under construction"/> + <supported-service>com.sun.star.security.Policy</supported-service> + <type>com.sun.star.security.XAccessController</type> + <type>com.sun.star.security.XPolicy</type> + <type>com.sun.star.security.RuntimePermission</type> + <type>com.sun.star.security.AllPermission</type> + <type>com.sun.star.io.FilePermission</type> + <type>com.sun.star.connection.SocketPermission</type> + <type>com.sun.star.registry.XRegistryKey</type> + <type>com.sun.star.lang.XTypeProvider</type> + <type>com.sun.star.lang.XComponent</type> + <type>com.sun.star.lang.XServiceInfo</type> + <type>com.sun.star.lang.XSingleComponentFactory</type> + <type>com.sun.star.lang.XSingleServiceFactory</type> + <type>com.sun.star.lang.XMultiComponentFactory</type> + <type>com.sun.star.lang.XMultiServiceFactory</type> + <type>com.sun.star.uno.XWeak</type> + <type>com.sun.star.uno.XAggregation</type> + <type>com.sun.star.uno.XCurrentContext</type> + <type>com.sun.star.uno.XComponentContext</type> + <type>com.sun.star.uno.TypeClass</type> + </component-description> + <component-description> + <author> Juergen Schmidt </author> + <name> com.sun.star.comp.stoc.SimpleRegistry </name> + <description> + This component provides access to a simple hierachical registry. The registry based on + one registry file. +</description> + <loader-name> com.sun.star.loader.SharedLibrary </loader-name> + <language> c++ </language> + <status value="final"/> + <supported-service> com.sun.star.registry.SimpleRegistry </supported-service> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XSingleComponentFactory </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XMultiComponentFactory </type> + <type> com.sun.star.registry.XSimpleRegistry </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.uno.TypeClass </type> + <type> com.sun.star.uno.XComponentContext </type> + </component-description> + <component-description> + <author> Juergen Schmidt </author> + <name> com.sun.star.comp.stoc.OServiceManager </name> + <description> + This component provides an administration object which manages + factories for many services. The services could be accessed with + the service name by using createInstance or createInstanceWithArguments. + To support the servicemanager with the needed information about a + service implementation, for e.g. which component implements the service, + two ways are possible: + - register a component persistent in a registry on which the servicemanager + works, using the com.sun.star.registry.ImplementationRegistration service. + - insert a corresponding factory for the service directly using the + interface XSet. + + For creating an object of a requested service the service manager checks + if a factory for this service is avaible, if not the registry will be + searched for information about this service. If there is an appropriate + entry, the component is loaded, a factory is created and announced to the + service manager. Finding a factory the service manager calls the factory + for creating new objects. +</description> + <loader-name> com.sun.star.loader.SharedLibrary </loader-name> + <language> c++ </language> + <status value="final"/> + <supported-service> com.sun.star.lang.MultiServiceFactory </supported-service> + <supported-service> com.sun.star.lang.ServiceManager </supported-service> + <type> com.sun.star.lang.XUnoTunnel </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XEventListener </type> + <type> com.sun.star.lang.XInitialization </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XSingleComponentFactory </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.DisposedException </type> + <type> com.sun.star.registry.XSimpleRegistry </type> + <type> com.sun.star.beans.XPropertySet </type> + <type> com.sun.star.container.XSet </type> + <type> com.sun.star.container.XEnumeration </type> + <type> com.sun.star.container.XContentEnumerationAccess </type> + <type> com.sun.star.container.XHierarchicalNameAccess </type> + <type> com.sun.star.uno.XComponentContext </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.uno.TypeClass </type> + <type> com.sun.star.uno.XUnloadingPreference </type> + <type> com.sun.star.beans.PropertyAttribute </type> + </component-description> + <component-description> + <author> Daniel Boelzle </author> + <name> com.sun.star.comp.stoc.TypeDescriptionManager </name> + <description> +This service is the central manager supporting the XHierarchicalNameAccess interface. +At runtime there will only be at most a single instance of the service. +A manager instance is hooked into the C UNO runtime typelib and lives until the service manager +is going down. +You can manually add a provider by inserting it via the XSet interface. +At startup of this service, you must call an initialization, adding all known +providers. +</description> + <loader-name> com.sun.star.loader.SharedLibrary </loader-name> + <language> C++ </language> + <status value="final"/> + <supported-service> com.sun.star.reflection.TypeDescriptionManager </supported-service> + <service-dependency> ... </service-dependency> + <type> com.sun.star.beans.PropertyAttribute </type> + <type> com.sun.star.reflection.XTypeDescription </type> + <type> com.sun.star.reflection.XEnumTypeDescription </type> + <type> com.sun.star.reflection.XArrayTypeDescription </type> + <type> com.sun.star.reflection.XIndirectTypeDescription </type> + <type> com.sun.star.reflection.XInterfaceMemberTypeDescription </type> + <type> com.sun.star.reflection.XInterfaceAttributeTypeDescription </type> + <type> com.sun.star.reflection.XInterfaceAttributeTypeDescription2 </type> + <type> com.sun.star.reflection.XMethodParameter </type> + <type> com.sun.star.reflection.XInterfaceMethodTypeDescription </type> + <type> com.sun.star.reflection.XInterfaceTypeDescription2 </type> + <type> com.sun.star.reflection.XStructTypeDescription </type> + <type> com.sun.star.reflection.XServiceTypeDescription </type> + <type> com.sun.star.reflection.XServiceTypeDescription2 </type> + <type> com.sun.star.reflection.XPropertyTypeDescription </type> + <type> com.sun.star.reflection.XConstantTypeDescription </type> + <type> com.sun.star.reflection.XConstantsTypeDescription </type> + <type> com.sun.star.reflection.XSingletonTypeDescription </type> + <type> com.sun.star.reflection.XSingletonTypeDescription2 </type> + <type> com.sun.star.reflection.XUnionTypeDescription </type> + <type> com.sun.star.reflection.XTypeDescriptionEnumerationAccess </type> + <type> com.sun.star.lang.DisposedException </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XEventListener </type> + <type> com.sun.star.lang.XInitialization </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XSingleComponentFactory </type> + <type> com.sun.star.lang.XMultiComponentFactory </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.container.XSet </type> + <type> com.sun.star.container.XHierarchicalNameAccess </type> + <type> com.sun.star.container.XContentEnumerationAccess </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.uno.XComponentContext </type> + <type> com.sun.star.uno.TypeClass </type> + </component-description> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> sal </project-build-dependency> + <project-build-dependency> registry </project-build-dependency> + <project-build-dependency> store </project-build-dependency> + <project-build-dependency> salhelper </project-build-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> sal3 </runtime-module-dependency> + <runtime-module-dependency> reg3 </runtime-module-dependency> + <runtime-module-dependency> store3 </runtime-module-dependency> + <runtime-module-dependency> reg3 </runtime-module-dependency> + <runtime-module-dependency> store3 </runtime-module-dependency> + <runtime-module-dependency> salhelper3(COM) </runtime-module-dependency> + <runtime-module-dependency> salhelper3(COM) </runtime-module-dependency> +</module-description> diff --git a/stoc/source/bootstrap/makefile.mk b/stoc/source/bootstrap/makefile.mk new file mode 100644 index 000000000000..9eb1a11cbad9 --- /dev/null +++ b/stoc/source/bootstrap/makefile.mk @@ -0,0 +1,50 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME= stoc +TARGET = bootstrap +ENABLE_EXCEPTIONS=TRUE +BOOTSTRAP_SERVICE=TRUE +COMP1TYPELIST = bootstrap + +# --- openoffice.org.orig/Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# ------------------------------------------------------------------ + +.INCLUDE : ..$/cppumaker.mk + +# --- openoffice.org.orig/Files ------------------------------------------------------ + +SLOFILES= \ + $(SLO)$/services.obj + +# --- openoffice.org.orig/Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/stoc/source/bootstrap/services.cxx b/stoc/source/bootstrap/services.cxx new file mode 100644 index 000000000000..7d295f4de78c --- /dev/null +++ b/stoc/source/bootstrap/services.cxx @@ -0,0 +1,141 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include "bootstrapservices.hxx" + +#include "cppuhelper/factory.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "sal/types.h" +#include "uno/environment.h" +#include "uno/lbnames.h" + +#include <stdio.h> + +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace cppu; +using namespace osl; +using namespace rtl; + +extern rtl_StandardModuleCount g_moduleCount; + +using namespace stoc_bootstrap; + +static struct ImplementationEntry g_entries[] = +{ + //servicemanager + { + OServiceManager_CreateInstance, smgr_getImplementationName, + smgr_getSupportedServiceNames, createSingleComponentFactory, + &g_moduleCount.modCnt , 0 + }, + { + ORegistryServiceManager_CreateInstance, regsmgr_getImplementationName, + regsmgr_getSupportedServiceNames, createSingleComponentFactory, + &g_moduleCount.modCnt , 0 + }, + { + OServiceManagerWrapper_CreateInstance, smgr_wrapper_getImplementationName, + smgr_wrapper_getSupportedServiceNames, createSingleComponentFactory, + &g_moduleCount.modCnt , 0 + }, + //security + { + ac_create, ac_getImplementationName, + ac_getSupportedServiceNames, createSingleComponentFactory, + &g_moduleCount.modCnt, 0 + }, + { + filepolicy_create, filepolicy_getImplementationName, + filepolicy_getSupportedServiceNames, createSingleComponentFactory, + &g_moduleCount.modCnt, 0 + }, + //simpleregistry + { + SimpleRegistry_CreateInstance, simreg_getImplementationName, + simreg_getSupportedServiceNames, createSingleComponentFactory, + &g_moduleCount.modCnt , 0 + }, + //defaultregistry + { + NestedRegistry_CreateInstance, defreg_getImplementationName, + defreg_getSupportedServiceNames, createSingleComponentFactory, + &g_moduleCount.modCnt , 0 + }, + //implementationregistry + { + ImplementationRegistration_CreateInstance, impreg_getImplementationName, + impreg_getSupportedServiceNames, createSingleComponentFactory, + &g_moduleCount.modCnt , 0 + }, + //loader + { + DllComponentLoader_CreateInstance, loader_getImplementationName, + loader_getSupportedServiceNames, createSingleComponentFactory, + &g_moduleCount.modCnt , 0 + }, + //registry_tdprovider + { + ProviderImpl_create, rdbtdp_getImplementationName, + rdbtdp_getSupportedServiceNames, createSingleComponentFactory, + &g_moduleCount.modCnt , 0 + }, + //tdmanager + { + ManagerImpl_create, tdmgr_getImplementationName, + tdmgr_getSupportedServiceNames, createSingleComponentFactory, + &g_moduleCount.modCnt , 0 + }, + //end + { 0, 0, 0, 0, 0, 0 } +}; + +extern "C" +{ + +sal_Bool SAL_CALL component_canUnload( TimeValue *pTime ) +{ + return g_moduleCount.canUnload( &g_moduleCount , pTime ); +} + +//================================================================================================== +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} +//================================================================================================== +void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) +{ + return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries ); +} + +} diff --git a/stoc/source/corereflection/base.hxx b/stoc/source/corereflection/base.hxx new file mode 100644 index 000000000000..2ef60da60d0b --- /dev/null +++ b/stoc/source/corereflection/base.hxx @@ -0,0 +1,453 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +// #define TEST_LIST_CLASSES +// #define TRACE(x) OSL_TRACE(x) +#define TRACE(x) + +#include <osl/diagnose.h> +#include <osl/mutex.hxx> +#include <uno/mapping.hxx> +#include <uno/dispatcher.h> +#include <cppuhelper/weak.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/component.hxx> +#include <cppuhelper/typeprovider.hxx> + +#include "lrucache.hxx" + +#ifdef TEST_LIST_CLASSES +#include <list> +#include <algorithm> +#endif +#include <hash_map> + +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> + +#include <com/sun/star/reflection/XIdlClass.hpp> +#include <com/sun/star/reflection/XIdlReflection.hpp> +#include <com/sun/star/reflection/XIdlField.hpp> +#include <com/sun/star/reflection/XIdlField2.hpp> +#include <com/sun/star/reflection/XIdlMethod.hpp> + +using namespace std; +using namespace osl; +using namespace rtl; +using namespace cppu; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::reflection; +using namespace com::sun::star::container; + + +namespace stoc_corefl +{ + +#ifdef TEST_LIST_CLASSES +typedef list< OUString > ClassNameList; +extern ClassNameList g_aClassNames; +#endif + +//-------------------------------------------------------------------------------------------------- +Mutex & getMutexAccess(); + +//-------------------------------------------------------------------------------------------------- +inline bool td_equals( typelib_TypeDescription * pTD, typelib_TypeDescriptionReference * pType ) +{ + return (pTD->pWeakRef == pType || + (pTD->pTypeName->length == pType->pTypeName->length && + rtl_ustr_compare( pTD->pTypeName->buffer, pType->pTypeName->buffer ) == 0)); +} +//-------------------------------------------------------------------------------------------------- +inline typelib_TypeDescription * getTypeByName( const OUString & rName ) +{ + typelib_TypeDescription * pTypeDescr = 0; + typelib_typedescription_getByName( &pTypeDescr, rName.pData ); + if (! pTypeDescr->bComplete) + typelib_typedescription_complete( &pTypeDescr ); + return pTypeDescr; +} + +typedef std::hash_map< OUString, WeakReference< XIdlField >, + FctHashOUString, equal_to< OUString > > OUString2Field; +typedef std::hash_map< OUString, WeakReference< XIdlMethod >, + FctHashOUString, equal_to< OUString > > OUString2Method; + +//================================================================================================== +class IdlReflectionServiceImpl + : public OComponentHelper + , public XIdlReflection + , public XHierarchicalNameAccess + , public XServiceInfo +{ + Mutex _aComponentMutex; + Reference< XMultiServiceFactory > _xMgr; + Reference< XHierarchicalNameAccess > _xTDMgr; + + // caching + LRU_CacheAnyByOUString _aElements; + + Mapping _aCpp2Uno; + Mapping _aUno2Cpp; + + inline Reference< XIdlClass > constructClass( typelib_TypeDescription * pTypeDescr ); +public: + Reference< XHierarchicalNameAccess > getTDMgr() const + { return _xTDMgr; } + Reference< XMultiServiceFactory > getSMgr() const + { return _xMgr; } + + const Mapping & getCpp2Uno() throw(::com::sun::star::uno::RuntimeException); + const Mapping & getUno2Cpp() throw(::com::sun::star::uno::RuntimeException); + uno_Interface * mapToUno( const Any & rObj, typelib_InterfaceTypeDescription * pTo ) throw(::com::sun::star::uno::RuntimeException); + + // ctor/ dtor + IdlReflectionServiceImpl( const Reference< XComponentContext > & xContext ); + virtual ~IdlReflectionServiceImpl(); + + // XInterface + virtual Any SAL_CALL queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + // some XComponent part from OComponentHelper + virtual void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // XTypeProvider + virtual Sequence< Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // XIdlReflection + virtual Reference< XIdlClass > SAL_CALL forName( const OUString & rTypeName ) throw(::com::sun::star::uno::RuntimeException); + virtual Reference< XIdlClass > SAL_CALL getType( const Any & rObj ) throw(::com::sun::star::uno::RuntimeException); + + // XHierarchicalNameAccess + virtual Any SAL_CALL getByHierarchicalName( const OUString & rName ) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasByHierarchicalName( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException); + + Reference< XIdlClass > forType( typelib_TypeDescription * pTypeDescr ) throw(::com::sun::star::uno::RuntimeException); + Reference< XIdlClass > forType( typelib_TypeDescriptionReference * pRef ) throw(::com::sun::star::uno::RuntimeException); +}; + +//================================================================================================== +class IdlClassImpl + : public WeakImplHelper1< XIdlClass > +{ + IdlReflectionServiceImpl * _pReflection; + + OUString _aName; + TypeClass _eTypeClass; + + typelib_TypeDescription * _pTypeDescr; + +public: + typelib_TypeDescription * getTypeDescr() const + { return _pTypeDescr; } + IdlReflectionServiceImpl * getReflection() const + { return _pReflection; } + Reference< XMultiServiceFactory > getSMgr() const + { return _pReflection->getSMgr(); } + Reference< XHierarchicalNameAccess > getTDMgr() const + { return getReflection()->getTDMgr(); } + + // Ctor + IdlClassImpl( IdlReflectionServiceImpl * pReflection, + const OUString & rName, typelib_TypeClass eTypeClass, + typelib_TypeDescription * pTypeDescr ); + virtual ~IdlClassImpl(); + + // XIdlClassImpl default implementation + virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException); + virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL equals( const Reference< XIdlClass >& xType ) throw(::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isAssignableFrom( const Reference< XIdlClass > & xType ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL createObject( Any & rObj ) throw(::com::sun::star::uno::RuntimeException); + + // def impl ???? + virtual Sequence< Reference< XIdlClass > > SAL_CALL getClasses() throw(::com::sun::star::uno::RuntimeException); + virtual Reference< XIdlClass > SAL_CALL getClass( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< Reference< XIdlClass > > SAL_CALL getInterfaces() throw(::com::sun::star::uno::RuntimeException); + + // structs, interfaces + virtual Sequence< Reference< XIdlClass > > SAL_CALL getSuperclasses() throw(::com::sun::star::uno::RuntimeException); + // structs + virtual Reference< XIdlField > SAL_CALL getField( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< Reference< XIdlField > > SAL_CALL getFields() throw(::com::sun::star::uno::RuntimeException); + // interfaces + virtual Uik SAL_CALL getUik() throw(::com::sun::star::uno::RuntimeException); + virtual Reference< XIdlMethod > SAL_CALL getMethod( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< Reference< XIdlMethod > > SAL_CALL getMethods() throw(::com::sun::star::uno::RuntimeException); + // array + virtual Reference< XIdlClass > SAL_CALL getComponentType() throw(::com::sun::star::uno::RuntimeException); + virtual Reference< XIdlArray > SAL_CALL getArray() throw(::com::sun::star::uno::RuntimeException); +}; + +//================================================================================================== +class InterfaceIdlClassImpl + : public IdlClassImpl +{ + typedef pair< OUString, typelib_TypeDescription * > MemberInit; + + Sequence< Reference< XIdlClass > > _xSuperClasses; + + MemberInit * _pSortedMemberInit; // first methods, then attributes + OUString2Field _aName2Field; + OUString2Method _aName2Method; + sal_Int32 _nMethods; + sal_Int32 _nAttributes; + + void initMembers(); + +public: + typelib_InterfaceTypeDescription * getTypeDescr() const + { return (typelib_InterfaceTypeDescription *)IdlClassImpl::getTypeDescr(); } + + // ctor/ dtor + InterfaceIdlClassImpl( IdlReflectionServiceImpl * pReflection, + const OUString & rName, typelib_TypeClass eTypeClass, + typelib_TypeDescription * pTypeDescr ) + : IdlClassImpl( pReflection, rName, eTypeClass, pTypeDescr ) + , _pSortedMemberInit( 0 ) + , _nMethods( 0 ) + , _nAttributes( 0 ) + {} + virtual ~InterfaceIdlClassImpl(); + + // IdlClassImpl modifications + virtual sal_Bool SAL_CALL isAssignableFrom( const Reference< XIdlClass > & xType ) throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< Reference< XIdlClass > > SAL_CALL getSuperclasses() throw(::com::sun::star::uno::RuntimeException); + virtual Uik SAL_CALL getUik() throw(::com::sun::star::uno::RuntimeException); + virtual Reference< XIdlMethod > SAL_CALL getMethod( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< Reference< XIdlMethod > > SAL_CALL getMethods() throw(::com::sun::star::uno::RuntimeException); + virtual Reference< XIdlField > SAL_CALL getField( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< Reference< XIdlField > > SAL_CALL getFields() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL createObject( Any & rObj ) throw(::com::sun::star::uno::RuntimeException); +}; + +//================================================================================================== +class CompoundIdlClassImpl + : public IdlClassImpl +{ + Reference< XIdlClass > _xSuperClass; + + Sequence< Reference< XIdlField > > * _pFields; + OUString2Field _aName2Field; + +public: + typelib_CompoundTypeDescription * getTypeDescr() const + { return (typelib_CompoundTypeDescription *)IdlClassImpl::getTypeDescr(); } + + // ctor/ dtor + CompoundIdlClassImpl( IdlReflectionServiceImpl * pReflection, + const OUString & rName, typelib_TypeClass eTypeClass, + typelib_TypeDescription * pTypeDescr ) + : IdlClassImpl( pReflection, rName, eTypeClass, pTypeDescr ) + , _pFields( 0 ) + {} + virtual ~CompoundIdlClassImpl(); + + // IdlClassImpl modifications + virtual sal_Bool SAL_CALL isAssignableFrom( const Reference< XIdlClass > & xType ) throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< Reference< XIdlClass > > SAL_CALL getSuperclasses() throw(::com::sun::star::uno::RuntimeException); + virtual Reference< XIdlField > SAL_CALL getField( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< Reference< XIdlField > > SAL_CALL getFields() throw(::com::sun::star::uno::RuntimeException); +}; + +//================================================================================================== +class ArrayIdlClassImpl + : public IdlClassImpl + , public XIdlArray +{ +public: + typelib_IndirectTypeDescription * getTypeDescr() const + { return (typelib_IndirectTypeDescription *)IdlClassImpl::getTypeDescr(); } + + // ctor + ArrayIdlClassImpl( IdlReflectionServiceImpl * pReflection, + const OUString & rName, typelib_TypeClass eTypeClass, + typelib_TypeDescription * pTypeDescr ) + : IdlClassImpl( pReflection, rName, eTypeClass, pTypeDescr ) + {} + + virtual Any SAL_CALL queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + // XTypeProvider + virtual Sequence< Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // IdlClassImpl modifications + virtual sal_Bool SAL_CALL isAssignableFrom( const Reference< XIdlClass > & xType ) throw(::com::sun::star::uno::RuntimeException); + virtual Reference< XIdlClass > SAL_CALL getComponentType() throw(::com::sun::star::uno::RuntimeException); + virtual Reference< XIdlArray > SAL_CALL getArray() throw(::com::sun::star::uno::RuntimeException); + + // XIdlArray + virtual void SAL_CALL realloc( Any & rArray, sal_Int32 nLen ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getLen( const Any & rArray ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual Any SAL_CALL get( const Any & rArray, sal_Int32 nIndex ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::ArrayIndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL set( Any & rArray, sal_Int32 nIndex, const Any & rNewValue ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::ArrayIndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); +}; + +//================================================================================================== +class EnumIdlClassImpl + : public IdlClassImpl +{ + Sequence< Reference< XIdlField > > * _pFields; + OUString2Field _aName2Field; + +public: + typelib_EnumTypeDescription * getTypeDescr() const + { return (typelib_EnumTypeDescription *)IdlClassImpl::getTypeDescr(); } + + // ctor/ dtor + EnumIdlClassImpl( IdlReflectionServiceImpl * pReflection, + const OUString & rName, typelib_TypeClass eTypeClass, + typelib_TypeDescription * pTypeDescr ) + : IdlClassImpl( pReflection, rName, eTypeClass, pTypeDescr ) + , _pFields( 0 ) + {} + virtual ~EnumIdlClassImpl(); + + // IdlClassImpl modifications + virtual Reference< XIdlField > SAL_CALL getField( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< Reference< XIdlField > > SAL_CALL getFields() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL createObject( Any & rObj ) throw(::com::sun::star::uno::RuntimeException); +}; + +//================================================================================================== +class IdlMemberImpl + : public WeakImplHelper1< XIdlMember > +{ + IdlReflectionServiceImpl * _pReflection; + OUString _aName; + + typelib_TypeDescription * _pTypeDescr; + typelib_TypeDescription * _pDeclTypeDescr; + +protected: + Reference< XIdlClass > _xDeclClass; + +public: + IdlReflectionServiceImpl * getReflection() const + { return _pReflection; } + Reference< XMultiServiceFactory > getSMgr() const + { return _pReflection->getSMgr(); } + typelib_TypeDescription * getTypeDescr() const + { return _pTypeDescr; } + typelib_TypeDescription * getDeclTypeDescr() const + { return _pDeclTypeDescr; } + + // ctor/ dtor + IdlMemberImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName, + typelib_TypeDescription * pTypeDescr, typelib_TypeDescription * pDeclTypeDescr ); + virtual ~IdlMemberImpl(); + + // XIdlMember + virtual Reference< XIdlClass > SAL_CALL getDeclaringClass() throw(::com::sun::star::uno::RuntimeException); + virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); +}; + +//-------------------------------------------------------------------------------------------------- +// coerces to type descr pTo else queries for it: the interface pointer is returned via rDest +// ## type to XidlClass coercion possible +inline sal_Bool extract( + const Any & rObj, typelib_InterfaceTypeDescription * pTo, + Reference< XInterface > & rDest, + IdlReflectionServiceImpl * pRefl ) +{ + rDest.clear(); + if (0 != pTo) + { + if (! rObj.hasValue()) + return sal_True; + if (rObj.getValueTypeClass() == TypeClass_INTERFACE) + { + return ::uno_type_assignData( + &rDest, ((typelib_TypeDescription *)pTo)->pWeakRef, + const_cast< void * >( rObj.getValue() ), rObj.getValueTypeRef(), + reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface), + reinterpret_cast< uno_AcquireFunc >(cpp_acquire), + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + } + else if (rObj.getValueTypeClass() == TypeClass_TYPE) + { + rDest = pRefl->forType( reinterpret_cast< const Type * >( rObj.getValue() )->getTypeLibType() ); + return rDest.is(); + } + } + return sal_False; +} +//-------------------------------------------------------------------------------------------------- +inline sal_Bool coerce_assign( + void * pDest, typelib_TypeDescription * pTD, const Any & rSource, + IdlReflectionServiceImpl * pRefl ) +{ + if (pTD->eTypeClass == typelib_TypeClass_INTERFACE) + { + Reference< XInterface > xVal; + if (extract( rSource, (typelib_InterfaceTypeDescription *)pTD, xVal, pRefl )) + { + if (*(XInterface **)pDest) + (*(XInterface **)pDest)->release(); + *(XInterface **)pDest = xVal.get(); + if (*(XInterface **)pDest) + (*(XInterface **)pDest)->acquire(); + return sal_True; + } + return sal_False; + } + else if (pTD->eTypeClass == typelib_TypeClass_ANY) + { + return uno_assignData( + pDest, pTD, + (void *)&rSource, pTD, + reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface), + reinterpret_cast< uno_AcquireFunc >(cpp_acquire), + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + } + else + { + return uno_type_assignData( + pDest, pTD->pWeakRef, + (void *)rSource.getValue(), rSource.getValueTypeRef(), + reinterpret_cast< uno_QueryInterfaceFunc >(cpp_queryInterface), + reinterpret_cast< uno_AcquireFunc >(cpp_acquire), + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + } +} + +} + + diff --git a/stoc/source/corereflection/corefl.xml b/stoc/source/corereflection/corefl.xml new file mode 100644 index 000000000000..5dba80b6abff --- /dev/null +++ b/stoc/source/corereflection/corefl.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + <module-name> corereflection.uno </module-name> + <component-description> + <author> Daniel Boelzle </author> + <name> com.sun.star.comp.stoc.CoreReflection </name> + <description> +This service is the implementation of XIdlClassProvider. +The service provides reflection and access to all uno types +(interfaces, structs, enums, ...). +</description> + <loader-name> com.sun.star.loader.SharedLibrary </loader-name> + <language> C++ </language> + <status value="final"/> + <supported-service> com.sun.star.reflection.CoreReflection </supported-service> + <service-dependency> ... </service-dependency> + <type>com.sun.star.lang.DisposedException</type> + <type> com.sun.star.reflection.XTypeDescription </type> + <type> com.sun.star.reflection.XIdlReflection </type> + <type> com.sun.star.reflection.XIdlClass </type> + <type> com.sun.star.reflection.XIdlField2 </type> + <type> com.sun.star.container.XHierarchicalNameAccess </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleComponentFactory </type> + <type> com.sun.star.lang.XMultiComponentFactory </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.WrappedTargetRuntimeException </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.uno.XComponentContext </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.uno.TypeClass </type> + </component-description> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> sal </project-build-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> sal3 </runtime-module-dependency> +</module-description> diff --git a/stoc/source/corereflection/crarray.cxx b/stoc/source/corereflection/crarray.cxx new file mode 100644 index 000000000000..1546b2389fbb --- /dev/null +++ b/stoc/source/corereflection/crarray.cxx @@ -0,0 +1,232 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include <typelib/typedescription.h> +#include <uno/data.h> + +#include "base.hxx" + + +namespace stoc_corefl +{ + +// XInterface +//__________________________________________________________________________________________________ +Any ArrayIdlClassImpl::queryInterface( const Type & rType ) + throw(::com::sun::star::uno::RuntimeException) +{ + Any aRet( ::cppu::queryInterface( rType, static_cast< XIdlArray * >( this ) ) ); + return (aRet.hasValue() ? aRet : IdlClassImpl::queryInterface( rType )); +} +//__________________________________________________________________________________________________ +void ArrayIdlClassImpl::acquire() throw() +{ + IdlClassImpl::acquire(); +} +//__________________________________________________________________________________________________ +void ArrayIdlClassImpl::release() throw() +{ + IdlClassImpl::release(); +} + +// XTypeProvider +//__________________________________________________________________________________________________ +Sequence< Type > ArrayIdlClassImpl::getTypes() + throw (::com::sun::star::uno::RuntimeException) +{ + static OTypeCollection * s_pTypes = 0; + if (! s_pTypes) + { + MutexGuard aGuard( getMutexAccess() ); + if (! s_pTypes) + { + static OTypeCollection s_aTypes( + ::getCppuType( (const Reference< XIdlArray > *)0 ), + IdlClassImpl::getTypes() ); + s_pTypes = &s_aTypes; + } + } + return s_pTypes->getTypes(); +} +//__________________________________________________________________________________________________ +Sequence< sal_Int8 > ArrayIdlClassImpl::getImplementationId() + throw (::com::sun::star::uno::RuntimeException) +{ + static OImplementationId * s_pId = 0; + if (! s_pId) + { + MutexGuard aGuard( getMutexAccess() ); + if (! s_pId) + { + static OImplementationId s_aId; + s_pId = &s_aId; + } + } + return s_pId->getImplementationId(); +} + +// XIdlArray +//__________________________________________________________________________________________________ +void ArrayIdlClassImpl::realloc( Any & rArray, sal_Int32 nLen ) + throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + TypeClass eTC = rArray.getValueTypeClass(); + if (eTC != TypeClass_SEQUENCE && eTC != TypeClass_ARRAY) + { + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no sequence given!") ), + (XWeak *)(OWeakObject *)this, 0 ); + } + if (nLen < 0) + { + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal length given!") ), + (XWeak *)(OWeakObject *)this, 1 ); + } + + uno_Sequence ** ppSeq = (uno_Sequence **)rArray.getValue(); + uno_sequence_realloc( ppSeq, (typelib_TypeDescription *)getTypeDescr(), + nLen, + reinterpret_cast< uno_AcquireFunc >(cpp_acquire), + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + rArray.pData = ppSeq; +} +//__________________________________________________________________________________________________ +sal_Int32 ArrayIdlClassImpl::getLen( const Any & rArray ) + throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + TypeClass eTC = rArray.getValueTypeClass(); + if (eTC != TypeClass_SEQUENCE && eTC != TypeClass_ARRAY) + { + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no sequence given!") ), + (XWeak *)(OWeakObject *)this, 0 ); + } + + return (*(uno_Sequence **)rArray.getValue())->nElements; +} +//__________________________________________________________________________________________________ +Any ArrayIdlClassImpl::get( const Any & rArray, sal_Int32 nIndex ) + throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::ArrayIndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException) +{ + TypeClass eTC = rArray.getValueTypeClass(); + if (eTC != TypeClass_SEQUENCE && eTC != TypeClass_ARRAY) + { + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no sequence given!") ), + (XWeak *)(OWeakObject *)this, 0 ); + } + + uno_Sequence * pSeq = *(uno_Sequence **)rArray.getValue(); + if (pSeq->nElements <= nIndex) + { + throw ArrayIndexOutOfBoundsException( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal index given!") ), + (XWeak *)(OWeakObject *)this ); + } + + Any aRet; + typelib_TypeDescription * pElemTypeDescr = 0; + TYPELIB_DANGER_GET( &pElemTypeDescr, getTypeDescr()->pType ); + uno_any_destruct( &aRet, reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + uno_any_construct( &aRet, &pSeq->elements[nIndex * pElemTypeDescr->nSize], + pElemTypeDescr, + reinterpret_cast< uno_AcquireFunc >(cpp_acquire) ); + TYPELIB_DANGER_RELEASE( pElemTypeDescr ); + return aRet; +} + +//__________________________________________________________________________________________________ +void ArrayIdlClassImpl::set( Any & rArray, sal_Int32 nIndex, const Any & rNewValue ) + throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::ArrayIndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException) +{ + TypeClass eTC = rArray.getValueTypeClass(); + if (eTC != TypeClass_SEQUENCE && eTC != TypeClass_ARRAY) + { + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no sequence given!") ), + (XWeak *)(OWeakObject *)this, 0 ); + } + + uno_Sequence * pSeq = *(uno_Sequence **)rArray.getValue(); + if (pSeq->nElements <= nIndex) + { + throw ArrayIndexOutOfBoundsException( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal index given!") ), + (XWeak *)(OWeakObject *)this ); + } + + uno_Sequence ** ppSeq = (uno_Sequence **)rArray.getValue(); + uno_sequence_reference2One( + ppSeq, (typelib_TypeDescription *)getTypeDescr(), + reinterpret_cast< uno_AcquireFunc >(cpp_acquire), + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + rArray.pData = ppSeq; + pSeq = *ppSeq; + + typelib_TypeDescription * pElemTypeDescr = 0; + TYPELIB_DANGER_GET( &pElemTypeDescr, getTypeDescr()->pType ); + + if (! coerce_assign( &pSeq->elements[nIndex * pElemTypeDescr->nSize], + pElemTypeDescr, rNewValue, getReflection() )) + { + TYPELIB_DANGER_RELEASE( pElemTypeDescr ); + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("sequence element is not assignable by given value!") ), + (XWeak *)(OWeakObject *)this, 2 ); + } + TYPELIB_DANGER_RELEASE( pElemTypeDescr ); +} + +// ArrayIdlClassImpl +//__________________________________________________________________________________________________ +sal_Bool ArrayIdlClassImpl::isAssignableFrom( const Reference< XIdlClass > & xType ) + throw(::com::sun::star::uno::RuntimeException) +{ + return (xType.is() && + (equals( xType ) || + (xType->getTypeClass() == getTypeClass() && // must be sequence|array + getComponentType()->isAssignableFrom( xType->getComponentType() )))); +} +//__________________________________________________________________________________________________ +Reference< XIdlClass > ArrayIdlClassImpl::getComponentType() + throw(::com::sun::star::uno::RuntimeException) +{ + return getReflection()->forType( getTypeDescr()->pType ); +} +//__________________________________________________________________________________________________ +Reference< XIdlArray > ArrayIdlClassImpl::getArray() + throw(::com::sun::star::uno::RuntimeException) +{ + return this; +} + +} + + diff --git a/stoc/source/corereflection/crbase.cxx b/stoc/source/corereflection/crbase.cxx new file mode 100644 index 000000000000..93d6aa4f2d24 --- /dev/null +++ b/stoc/source/corereflection/crbase.cxx @@ -0,0 +1,291 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include <cppuhelper/queryinterface.hxx> +#include <uno/any2.h> + +#include "base.hxx" + +namespace stoc_corefl +{ + +#ifdef TEST_LIST_CLASSES +ClassNameList g_aClassNames; +#endif + +//-------------------------------------------------------------------------------------------------- +Mutex & getMutexAccess() +{ + static Mutex * s_pMutex = 0; + if (! s_pMutex) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! s_pMutex) + { + static Mutex s_aMutex; + s_pMutex = &s_aMutex; + } + } + return *s_pMutex; +} + +//__________________________________________________________________________________________________ +IdlClassImpl::IdlClassImpl( IdlReflectionServiceImpl * pReflection, + const OUString & rName, typelib_TypeClass eTypeClass, + typelib_TypeDescription * pTypeDescr ) + : _pReflection( pReflection ) + , _aName( rName ) + , _eTypeClass( (TypeClass)eTypeClass ) + , _pTypeDescr( pTypeDescr ) +{ + if (_pReflection) + _pReflection->acquire(); + if (_pTypeDescr) + { + typelib_typedescription_acquire( _pTypeDescr ); + if (! _pTypeDescr->bComplete) + typelib_typedescription_complete( &_pTypeDescr ); + } + +#ifdef TEST_LIST_CLASSES + ClassNameList::const_iterator iFind( find( g_aClassNames.begin(), g_aClassNames.end(), _aName ) ); + OSL_ENSURE( iFind == g_aClassNames.end(), "### idl class already exists!" ); + g_aClassNames.push_front( _aName ); +#endif +} +//__________________________________________________________________________________________________ +IdlClassImpl::~IdlClassImpl() +{ + if (_pTypeDescr) + typelib_typedescription_release( _pTypeDescr ); + if (_pReflection) + _pReflection->release(); + +#ifdef TEST_LIST_CLASSES + ClassNameList::iterator iFind( find( g_aClassNames.begin(), g_aClassNames.end(), _aName ) ); + OSL_ENSURE( iFind != g_aClassNames.end(), "### idl class does not exist!" ); + g_aClassNames.erase( iFind ); +#endif +} + +// XIdlClassImpl default implementation +//__________________________________________________________________________________________________ +TypeClass IdlClassImpl::getTypeClass() + throw(::com::sun::star::uno::RuntimeException) +{ + return _eTypeClass; +} +//__________________________________________________________________________________________________ +OUString IdlClassImpl::getName() + throw(::com::sun::star::uno::RuntimeException) +{ + return _aName; +} +//__________________________________________________________________________________________________ +sal_Bool IdlClassImpl::equals( const Reference< XIdlClass >& xType ) + throw(::com::sun::star::uno::RuntimeException) +{ + return (xType.is() && + (xType->getTypeClass() == _eTypeClass) && (xType->getName() == _aName)); +} + +static sal_Bool s_aAssignableFromTab[11][11] = +{ + /* from CH,BO,BY,SH,US,LO,UL,HY,UH,FL,DO */ +/* TypeClass_CHAR */ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, +/* TypeClass_BOOLEAN */ { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, +/* TypeClass_BYTE */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, +/* TypeClass_SHORT */ { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0 }, +/* TypeClass_UNSIGNED_SHORT */ { 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0 }, +/* TypeClass_LONG */ { 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, +/* TypeClass_UNSIGNED_LONG */ { 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, +/* TypeClass_HYPER */ { 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0 }, +/* TypeClass_UNSIGNED_HYPER */ { 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0 }, +/* TypeClass_FLOAT */ { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0 }, +/* TypeClass_DOUBLE */ { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 } +}; +//__________________________________________________________________________________________________ +sal_Bool IdlClassImpl::isAssignableFrom( const Reference< XIdlClass > & xType ) + throw(::com::sun::star::uno::RuntimeException) +{ + TypeClass eAssign = getTypeClass(); + if (equals( xType ) || eAssign == TypeClass_ANY) // default shot + { + return sal_True; + } + else + { + TypeClass eFrom = xType->getTypeClass(); + if (eAssign > TypeClass_VOID && eAssign < TypeClass_STRING && + eFrom > TypeClass_VOID && eFrom < TypeClass_STRING) + { + return s_aAssignableFromTab[eAssign-1][eFrom-1]; + } + } + return sal_False; +} +//__________________________________________________________________________________________________ +void IdlClassImpl::createObject( Any & rObj ) + throw(::com::sun::star::uno::RuntimeException) +{ + rObj.clear(); + uno_any_destruct( &rObj, reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + uno_any_construct( &rObj, 0, getTypeDescr(), 0 ); +} + +// what TODO ???? +//__________________________________________________________________________________________________ +Sequence< Reference< XIdlClass > > IdlClassImpl::getClasses() + throw(::com::sun::star::uno::RuntimeException) +{ + OSL_ENSURE( sal_False, "### unexpected use!" ); + return Sequence< Reference< XIdlClass > >(); +} +//__________________________________________________________________________________________________ +Reference< XIdlClass > IdlClassImpl::getClass( const OUString & ) + throw(::com::sun::star::uno::RuntimeException) +{ + OSL_ENSURE( sal_False, "### unexpected use!" ); + return Reference< XIdlClass >(); +} +//__________________________________________________________________________________________________ +Sequence< Reference< XIdlClass > > IdlClassImpl::getInterfaces() + throw(::com::sun::star::uno::RuntimeException) +{ +// OSL_ENSURE( sal_False, "### unexpected use!" ); + return Sequence< Reference< XIdlClass > >(); +} + +// structs, interfaces +//__________________________________________________________________________________________________ +Sequence< Reference< XIdlClass > > IdlClassImpl::getSuperclasses() throw(::com::sun::star::uno::RuntimeException) +{ + return Sequence< Reference< XIdlClass > >(); +} +// structs +//__________________________________________________________________________________________________ +Reference< XIdlField > IdlClassImpl::getField( const OUString & ) + throw(::com::sun::star::uno::RuntimeException) +{ + return Reference< XIdlField >(); +} +//__________________________________________________________________________________________________ +Sequence< Reference< XIdlField > > IdlClassImpl::getFields() + throw(::com::sun::star::uno::RuntimeException) +{ + return Sequence< Reference< XIdlField > >(); +} +// interfaces +//__________________________________________________________________________________________________ +Uik IdlClassImpl::getUik() + throw(::com::sun::star::uno::RuntimeException) +{ + return Uik(); +} +//__________________________________________________________________________________________________ +Reference< XIdlMethod > IdlClassImpl::getMethod( const OUString & ) + throw(::com::sun::star::uno::RuntimeException) +{ + return Reference< XIdlMethod >(); +} +//__________________________________________________________________________________________________ +Sequence< Reference< XIdlMethod > > IdlClassImpl::getMethods() + throw(::com::sun::star::uno::RuntimeException) +{ + return Sequence< Reference< XIdlMethod > >(); +} +// array +//__________________________________________________________________________________________________ +Reference< XIdlClass > IdlClassImpl::getComponentType() + throw(::com::sun::star::uno::RuntimeException) +{ + return Reference< XIdlClass >(); +} +//__________________________________________________________________________________________________ +Reference< XIdlArray > IdlClassImpl::getArray() + throw(::com::sun::star::uno::RuntimeException) +{ + return Reference< XIdlArray >(); +} + + +//################################################################################################## +//################################################################################################## +//################################################################################################## + + +//__________________________________________________________________________________________________ +IdlMemberImpl::IdlMemberImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName, + typelib_TypeDescription * pTypeDescr, + typelib_TypeDescription * pDeclTypeDescr ) + : _pReflection( pReflection ) + , _aName( rName ) + , _pTypeDescr( pTypeDescr ) + , _pDeclTypeDescr( pDeclTypeDescr ) +{ + _pReflection->acquire(); + typelib_typedescription_acquire( _pTypeDescr ); + if (! _pTypeDescr->bComplete) + typelib_typedescription_complete( &_pTypeDescr ); + typelib_typedescription_acquire( _pDeclTypeDescr ); + if (! _pDeclTypeDescr->bComplete) + typelib_typedescription_complete( &_pDeclTypeDescr ); +} +//__________________________________________________________________________________________________ +IdlMemberImpl::~IdlMemberImpl() +{ + typelib_typedescription_release( _pDeclTypeDescr ); + typelib_typedescription_release( _pTypeDescr ); + _pReflection->release(); +} + +// XIdlMember +//__________________________________________________________________________________________________ +Reference< XIdlClass > IdlMemberImpl::getDeclaringClass() + throw(::com::sun::star::uno::RuntimeException) +{ + if (! _xDeclClass.is()) + { + Reference< XIdlClass > xDeclClass( getReflection()->forType( getDeclTypeDescr() ) ); + MutexGuard aGuard( getMutexAccess() ); + if (! _xDeclClass.is()) + _xDeclClass = xDeclClass; + } + return _xDeclClass; +} +//__________________________________________________________________________________________________ +OUString IdlMemberImpl::getName() + throw(::com::sun::star::uno::RuntimeException) +{ + return _aName; +} + +} + + diff --git a/stoc/source/corereflection/crcomp.cxx b/stoc/source/corereflection/crcomp.cxx new file mode 100644 index 000000000000..db3c2741322f --- /dev/null +++ b/stoc/source/corereflection/crcomp.cxx @@ -0,0 +1,405 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include <rtl/strbuf.hxx> + +#include <com/sun/star/reflection/XIdlField.hpp> +#include <com/sun/star/reflection/XIdlField2.hpp> +#include "com/sun/star/uno/TypeClass.hpp" + +#include "base.hxx" + + +namespace stoc_corefl +{ + +//================================================================================================== +class IdlCompFieldImpl + : public IdlMemberImpl + , public XIdlField + , public XIdlField2 +{ + sal_Int32 _nOffset; + +public: + IdlCompFieldImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName, + typelib_TypeDescription * pTypeDescr, typelib_TypeDescription * pDeclTypeDescr, + sal_Int32 nOffset ) + : IdlMemberImpl( pReflection, rName, pTypeDescr, pDeclTypeDescr ) + , _nOffset( nOffset ) + {} + + // XInterface + virtual Any SAL_CALL queryInterface( const Type & rType ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw (); + virtual void SAL_CALL release() throw (); + + // XTypeProvider + virtual Sequence< Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // XIdlMember + virtual Reference< XIdlClass > SAL_CALL getDeclaringClass() throw(::com::sun::star::uno::RuntimeException); + virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); + // XIdlField + virtual Reference< XIdlClass > SAL_CALL getType() throw(::com::sun::star::uno::RuntimeException); + virtual FieldAccessMode SAL_CALL getAccessMode() throw(::com::sun::star::uno::RuntimeException); + virtual Any SAL_CALL get( const Any & rObj ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL set( const Any & rObj, const Any & rValue ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException); + // XIdlField2: getType, getAccessMode and get are equal to XIdlField + virtual void SAL_CALL set( Any & rObj, const Any & rValue ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException); +}; + +// XInterface +//__________________________________________________________________________________________________ +Any IdlCompFieldImpl::queryInterface( const Type & rType ) + throw(::com::sun::star::uno::RuntimeException) +{ + Any aRet( ::cppu::queryInterface( rType, + static_cast< XIdlField * >( this ), + static_cast< XIdlField2 * >( this ) ) ); + return (aRet.hasValue() ? aRet : IdlMemberImpl::queryInterface( rType )); +} +//__________________________________________________________________________________________________ +void IdlCompFieldImpl::acquire() throw() +{ + IdlMemberImpl::acquire(); +} +//__________________________________________________________________________________________________ +void IdlCompFieldImpl::release() throw() +{ + IdlMemberImpl::release(); +} + +// XTypeProvider +//__________________________________________________________________________________________________ +Sequence< Type > IdlCompFieldImpl::getTypes() + throw (::com::sun::star::uno::RuntimeException) +{ + static OTypeCollection * s_pTypes = 0; + if (! s_pTypes) + { + MutexGuard aGuard( getMutexAccess() ); + if (! s_pTypes) + { + static OTypeCollection s_aTypes( + ::getCppuType( (const Reference< XIdlField2 > *)0 ), + ::getCppuType( (const Reference< XIdlField > *)0 ), + IdlMemberImpl::getTypes() ); + s_pTypes = &s_aTypes; + } + } + return s_pTypes->getTypes(); +} +//__________________________________________________________________________________________________ +Sequence< sal_Int8 > IdlCompFieldImpl::getImplementationId() + throw (::com::sun::star::uno::RuntimeException) +{ + static OImplementationId * s_pId = 0; + if (! s_pId) + { + MutexGuard aGuard( getMutexAccess() ); + if (! s_pId) + { + static OImplementationId s_aId; + s_pId = &s_aId; + } + } + return s_pId->getImplementationId(); +} + +// XIdlMember +//__________________________________________________________________________________________________ +Reference< XIdlClass > IdlCompFieldImpl::getDeclaringClass() + throw(::com::sun::star::uno::RuntimeException) +{ + if (! _xDeclClass.is()) + { + MutexGuard aGuard( getMutexAccess() ); + if (! _xDeclClass.is()) + { + typelib_CompoundTypeDescription * pTD = + (typelib_CompoundTypeDescription *)getDeclTypeDescr(); + while (pTD) + { + typelib_TypeDescriptionReference ** ppTypeRefs = pTD->ppTypeRefs; + for ( sal_Int32 nPos = pTD->nMembers; nPos--; ) + { + if (td_equals( (typelib_TypeDescription *)getTypeDescr(), ppTypeRefs[nPos] )) + { + _xDeclClass = getReflection()->forType( (typelib_TypeDescription *)pTD ); + return _xDeclClass; + } + } + pTD = pTD->pBaseTypeDescription; + } + } + } + return _xDeclClass; +} +//__________________________________________________________________________________________________ +OUString IdlCompFieldImpl::getName() + throw(::com::sun::star::uno::RuntimeException) +{ + return IdlMemberImpl::getName(); +} + +// XIdlField +//__________________________________________________________________________________________________ +Reference< XIdlClass > IdlCompFieldImpl::getType() + throw(::com::sun::star::uno::RuntimeException) +{ + return getReflection()->forType( getTypeDescr() ); +} +//__________________________________________________________________________________________________ +FieldAccessMode IdlCompFieldImpl::getAccessMode() + throw(::com::sun::star::uno::RuntimeException) +{ + return FieldAccessMode_READWRITE; +} +//__________________________________________________________________________________________________ +Any IdlCompFieldImpl::get( const Any & rObj ) + throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + if (rObj.getValueTypeClass() == com::sun::star::uno::TypeClass_STRUCT || + rObj.getValueTypeClass() == com::sun::star::uno::TypeClass_EXCEPTION) + { + typelib_TypeDescription * pObjTD = 0; + TYPELIB_DANGER_GET( &pObjTD, rObj.getValueTypeRef() ); + + typelib_TypeDescription * pTD = pObjTD; + typelib_TypeDescription * pDeclTD = getDeclTypeDescr(); + while (pTD && !typelib_typedescription_equals( pTD, pDeclTD )) + pTD = (typelib_TypeDescription *)((typelib_CompoundTypeDescription *)pTD)->pBaseTypeDescription; + + OSL_ENSURE( pTD, "### illegal object type!" ); + if (pTD) + { + TYPELIB_DANGER_RELEASE( pObjTD ); + Any aRet; + uno_any_destruct( + &aRet, reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + uno_any_construct( + &aRet, (char *)rObj.getValue() + _nOffset, getTypeDescr(), + reinterpret_cast< uno_AcquireFunc >(cpp_acquire) ); + return aRet; + } + TYPELIB_DANGER_RELEASE( pObjTD ); + } + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal object given!") ), + (XWeak *)(OWeakObject *)this, 0 ); +} +//__________________________________________________________________________________________________ +void IdlCompFieldImpl::set( const Any & rObj, const Any & rValue ) + throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException) +{ + if (rObj.getValueTypeClass() == com::sun::star::uno::TypeClass_STRUCT || + rObj.getValueTypeClass() == com::sun::star::uno::TypeClass_EXCEPTION) + { + typelib_TypeDescription * pObjTD = 0; + TYPELIB_DANGER_GET( &pObjTD, rObj.getValueTypeRef() ); + + typelib_TypeDescription * pTD = pObjTD; + typelib_TypeDescription * pDeclTD = getDeclTypeDescr(); + while (pTD && !typelib_typedescription_equals( pTD, pDeclTD )) + pTD = (typelib_TypeDescription *)((typelib_CompoundTypeDescription *)pTD)->pBaseTypeDescription; + + OSL_ENSURE( pTD, "### illegal object type!" ); + if (pTD) + { + TYPELIB_DANGER_RELEASE( pObjTD ); + if (coerce_assign( (char *)rObj.getValue() + _nOffset, getTypeDescr(), rValue, getReflection() )) + { + return; + } + else + { + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal value given!") ), + (XWeak *)(OWeakObject *)this, 1 ); + } + } + TYPELIB_DANGER_RELEASE( pObjTD ); + } + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal object given!") ), + (XWeak *)(OWeakObject *)this, 0 ); +} + +//__________________________________________________________________________________________________ +void IdlCompFieldImpl::set( Any & rObj, const Any & rValue ) + throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException) +{ + if (rObj.getValueTypeClass() == com::sun::star::uno::TypeClass_STRUCT || + rObj.getValueTypeClass() == com::sun::star::uno::TypeClass_EXCEPTION) + { + typelib_TypeDescription * pObjTD = 0; + TYPELIB_DANGER_GET( &pObjTD, rObj.getValueTypeRef() ); + + typelib_TypeDescription * pTD = pObjTD; + typelib_TypeDescription * pDeclTD = getDeclTypeDescr(); + while (pTD && !typelib_typedescription_equals( pTD, pDeclTD )) + pTD = (typelib_TypeDescription *)((typelib_CompoundTypeDescription *)pTD)->pBaseTypeDescription; + + OSL_ENSURE( pTD, "### illegal object type!" ); + if (pTD) + { + TYPELIB_DANGER_RELEASE( pObjTD ); + if (coerce_assign( (char *)rObj.getValue() + _nOffset, getTypeDescr(), rValue, getReflection() )) + { + return; + } + else + { + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal value given!") ), + (XWeak *)(OWeakObject *)this, 1 ); + } + } + TYPELIB_DANGER_RELEASE( pObjTD ); + } + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal object given!") ), + (XWeak *)(OWeakObject *)this, 0 ); +} + +//################################################################################################## +//################################################################################################## +//################################################################################################## + + +//__________________________________________________________________________________________________ +CompoundIdlClassImpl::~CompoundIdlClassImpl() +{ + delete _pFields; +} + +//__________________________________________________________________________________________________ +sal_Bool CompoundIdlClassImpl::isAssignableFrom( const Reference< XIdlClass > & xType ) + throw(::com::sun::star::uno::RuntimeException) +{ + if (xType.is()) + { + TypeClass eTC = xType->getTypeClass(); + if (eTC == TypeClass_STRUCT || eTC == TypeClass_EXCEPTION) + { + if (equals( xType )) + return sal_True; + else + { + const Sequence< Reference< XIdlClass > > & rSeq = xType->getSuperclasses(); + if (rSeq.getLength()) + { + OSL_ENSURE( rSeq.getLength() == 1, "### unexpected len of super classes!" ); + return isAssignableFrom( rSeq[0] ); + } + } + } + } + return sal_False; +} +//__________________________________________________________________________________________________ +Sequence< Reference< XIdlClass > > CompoundIdlClassImpl::getSuperclasses() + throw(::com::sun::star::uno::RuntimeException) +{ + if (! _xSuperClass.is()) + { + MutexGuard aGuard( getMutexAccess() ); + if (! _xSuperClass.is()) + { + typelib_CompoundTypeDescription * pCompTypeDescr = getTypeDescr()->pBaseTypeDescription; + if (pCompTypeDescr) + _xSuperClass = getReflection()->forType( (typelib_TypeDescription *)pCompTypeDescr ); + } + } + if (_xSuperClass.is()) + return Sequence< Reference< XIdlClass > >( &_xSuperClass, 1 ); + else + return Sequence< Reference< XIdlClass > >(); +} +//__________________________________________________________________________________________________ +Reference< XIdlField > CompoundIdlClassImpl::getField( const OUString & rName ) + throw(::com::sun::star::uno::RuntimeException) +{ + if (! _pFields) + getFields(); // init fields + + const OUString2Field::const_iterator iFind( _aName2Field.find( rName ) ); + if (iFind != _aName2Field.end()) + return Reference< XIdlField >( (*iFind).second ); + else + return Reference< XIdlField >(); +} +//__________________________________________________________________________________________________ +Sequence< Reference< XIdlField > > CompoundIdlClassImpl::getFields() + throw(::com::sun::star::uno::RuntimeException) +{ + MutexGuard aGuard( getMutexAccess() ); + if (! _pFields) + { + sal_Int32 nAll = 0; + typelib_CompoundTypeDescription * pCompTypeDescr = getTypeDescr(); + for ( ; pCompTypeDescr; pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription ) + nAll += pCompTypeDescr->nMembers; + + Sequence< Reference< XIdlField > > * pFields = + new Sequence< Reference< XIdlField > >( nAll ); + Reference< XIdlField > * pSeq = pFields->getArray(); + + for ( pCompTypeDescr = getTypeDescr(); pCompTypeDescr; + pCompTypeDescr = pCompTypeDescr->pBaseTypeDescription ) + { + typelib_TypeDescriptionReference ** ppTypeRefs = pCompTypeDescr->ppTypeRefs; + rtl_uString ** ppNames = pCompTypeDescr->ppMemberNames; + sal_Int32 * pMemberOffsets = pCompTypeDescr->pMemberOffsets; + + for ( sal_Int32 nPos = pCompTypeDescr->nMembers; nPos--; ) + { + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, ppTypeRefs[nPos] ); + OSL_ENSURE( pTD, "### cannot get field in struct!" ); + if (pTD) + { + OUString aName( ppNames[nPos] ); + _aName2Field[aName] = pSeq[--nAll] = new IdlCompFieldImpl( + getReflection(), aName, pTD, IdlClassImpl::getTypeDescr(), pMemberOffsets[nPos] ); + TYPELIB_DANGER_RELEASE( pTD ); + } + } + } + + _pFields = pFields; + } + return *_pFields; +} + +} + + diff --git a/stoc/source/corereflection/crefl.cxx b/stoc/source/corereflection/crefl.cxx new file mode 100644 index 000000000000..d3ebed762bac --- /dev/null +++ b/stoc/source/corereflection/crefl.cxx @@ -0,0 +1,514 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include <cppuhelper/queryinterface.hxx> +#ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_ +#include <cppuhelper/implementationentry.hxx> +#endif + +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/reflection/XTypeDescription.hpp> +#include "com/sun/star/uno/RuntimeException.hpp" + +using namespace com::sun::star; +using namespace com::sun::star::lang; +using namespace com::sun::star::registry; +using namespace cppu; +using namespace osl; +using namespace rtl; + +#include "base.hxx" + + +namespace stoc_corefl +{ + +static const sal_Int32 CACHE_SIZE = 256; + +#define SERVICENAME "com.sun.star.reflection.CoreReflection" +#define IMPLNAME "com.sun.star.comp.stoc.CoreReflection" + +// can be static, as every client of the core reflection keeps a reference to the +// core reflection, so refcounting can be done here. +static rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT; + +static Sequence< OUString > core_getSupportedServiceNames() +{ + static Sequence < OUString > *pNames = 0; + if( ! pNames ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( !pNames ) + { + static Sequence< OUString > seqNames(1); + seqNames.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(SERVICENAME) ); + pNames = &seqNames; + } + } + return *pNames; +} + +static OUString core_getImplementationName() +{ + static OUString *pImplName = 0; + if( ! pImplName ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( ! pImplName ) + { + static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) ); + pImplName = &implName; + } + } + return *pImplName; +} +//__________________________________________________________________________________________________ +IdlReflectionServiceImpl::IdlReflectionServiceImpl( + const Reference< XComponentContext > & xContext ) + : OComponentHelper( _aComponentMutex ) + , _xMgr( xContext->getServiceManager(), UNO_QUERY ) + , _aElements( CACHE_SIZE ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + xContext->getValueByName( OUString( RTL_CONSTASCII_USTRINGPARAM( + "/singletons/com.sun.star.reflection.theTypeDescriptionManager") ) ) >>= _xTDMgr; + OSL_ENSURE( _xTDMgr.is(), "### cannot get singleton \"TypeDescriptionManager\" from context!" ); +} +//__________________________________________________________________________________________________ +IdlReflectionServiceImpl::~IdlReflectionServiceImpl() +{ + TRACE( "> IdlReflectionServiceImpl dtor <\n" ); + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +// XInterface +//__________________________________________________________________________________________________ +Any IdlReflectionServiceImpl::queryInterface( const Type & rType ) + throw(::com::sun::star::uno::RuntimeException) +{ + Any aRet( ::cppu::queryInterface( + rType, + static_cast< XIdlReflection * >( this ), + static_cast< XHierarchicalNameAccess * >( this ), + static_cast< XServiceInfo * >( this ) ) ); + + return (aRet.hasValue() ? aRet : OComponentHelper::queryInterface( rType )); +} +//__________________________________________________________________________________________________ +void IdlReflectionServiceImpl::acquire() throw() +{ + OComponentHelper::acquire(); +} +//__________________________________________________________________________________________________ +void IdlReflectionServiceImpl::release() throw() +{ + OComponentHelper::release(); +} + +// XTypeProvider +//__________________________________________________________________________________________________ +Sequence< Type > IdlReflectionServiceImpl::getTypes() + throw (::com::sun::star::uno::RuntimeException) +{ + static OTypeCollection * s_pTypes = 0; + if (! s_pTypes) + { + MutexGuard aGuard( _aComponentMutex ); + if (! s_pTypes) + { + static OTypeCollection s_aTypes( + ::getCppuType( (const Reference< XIdlReflection > *)0 ), + ::getCppuType( (const Reference< XHierarchicalNameAccess > *)0 ), + ::getCppuType( (const Reference< XServiceInfo > *)0 ), + OComponentHelper::getTypes() ); + s_pTypes = &s_aTypes; + } + } + return s_pTypes->getTypes(); +} +//__________________________________________________________________________________________________ +Sequence< sal_Int8 > IdlReflectionServiceImpl::getImplementationId() + throw (::com::sun::star::uno::RuntimeException) +{ + static OImplementationId * s_pId = 0; + if (! s_pId) + { + MutexGuard aGuard( _aComponentMutex ); + if (! s_pId) + { + static OImplementationId s_aId; + s_pId = &s_aId; + } + } + return s_pId->getImplementationId(); +} + +// XComponent +//__________________________________________________________________________________________________ +void IdlReflectionServiceImpl::dispose() + throw(::com::sun::star::uno::RuntimeException) +{ + TRACE( "> disposing corereflection... <" ); + OComponentHelper::dispose(); + + MutexGuard aGuard( _aComponentMutex ); + _aElements.clear(); +#ifdef TEST_LIST_CLASSES + OSL_ENSURE( g_aClassNames.size() == 0, "### idl classes still alive!" ); + ClassNameList::const_iterator iPos( g_aClassNames.begin() ); + while (iPos != g_aClassNames.end()) + { + OUString aName( *iPos ); + ++iPos; + } +#endif +} + +// XServiceInfo +//__________________________________________________________________________________________________ +OUString IdlReflectionServiceImpl::getImplementationName() + throw(::com::sun::star::uno::RuntimeException) +{ + return core_getImplementationName(); +} +//__________________________________________________________________________________________________ +sal_Bool IdlReflectionServiceImpl::supportsService( const OUString & rServiceName ) + throw(::com::sun::star::uno::RuntimeException) +{ + const Sequence< OUString > & rSNL = getSupportedServiceNames(); + const OUString * pArray = rSNL.getConstArray(); + for ( sal_Int32 nPos = rSNL.getLength(); nPos--; ) + { + if (pArray[nPos] == rServiceName) + return sal_True; + } + return sal_False; +} +//__________________________________________________________________________________________________ +Sequence< OUString > IdlReflectionServiceImpl::getSupportedServiceNames() + throw(::com::sun::star::uno::RuntimeException) +{ + return core_getSupportedServiceNames(); +} + +// XIdlReflection +//__________________________________________________________________________________________________ +Reference< XIdlClass > IdlReflectionServiceImpl::getType( const Any & rObj ) + throw(::com::sun::star::uno::RuntimeException) +{ + return (rObj.hasValue() ? forType( rObj.getValueTypeRef() ) : Reference< XIdlClass >()); +} + +//__________________________________________________________________________________________________ +inline Reference< XIdlClass > IdlReflectionServiceImpl::constructClass( + typelib_TypeDescription * pTypeDescr ) +{ + OSL_ENSURE( pTypeDescr->eTypeClass != typelib_TypeClass_TYPEDEF, "### unexpected typedef!" ); + + switch (pTypeDescr->eTypeClass) + { + case typelib_TypeClass_VOID: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_FLOAT: + case typelib_TypeClass_DOUBLE: + case typelib_TypeClass_STRING: + case typelib_TypeClass_ANY: + return new IdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr ); + + case TypeClass_ENUM: + return new EnumIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr ); + + case typelib_TypeClass_STRUCT: + case typelib_TypeClass_UNION: + case typelib_TypeClass_EXCEPTION: + return new CompoundIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr ); + + case typelib_TypeClass_ARRAY: + case typelib_TypeClass_SEQUENCE: + return new ArrayIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr ); + + case typelib_TypeClass_INTERFACE: + return new InterfaceIdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr ); + + case typelib_TypeClass_TYPE: + return new IdlClassImpl( this, pTypeDescr->pTypeName, pTypeDescr->eTypeClass, pTypeDescr ); + + default: +#if OSL_DEBUG_LEVEL > 1 + OSL_TRACE( "### corereflection type unsupported: " ); + OString aName( OUStringToOString( pTypeDescr->pTypeName, RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( aName.getStr() ); + OSL_TRACE( "\n" ); +#endif + return Reference< XIdlClass >(); + } +} +//__________________________________________________________________________________________________ +Reference< XIdlClass > IdlReflectionServiceImpl::forName( const OUString & rTypeName ) + throw(::com::sun::star::uno::RuntimeException) +{ + Reference< XIdlClass > xRet; + Any aAny( _aElements.getValue( rTypeName ) ); + + if (aAny.hasValue()) + { + if (aAny.getValueTypeClass() == TypeClass_INTERFACE) + xRet = *(const Reference< XIdlClass > *)aAny.getValue(); + } + else + { + // try to get _type_ by name + typelib_TypeDescription * pTD = 0; + typelib_typedescription_getByName( &pTD, rTypeName.pData ); + if (pTD) + { + if ((xRet = constructClass( pTD )).is()) + _aElements.setValue( rTypeName, makeAny( xRet ) ); // update + typelib_typedescription_release( pTD ); + } + } + + return xRet; +} + +// XHierarchicalNameAccess +//__________________________________________________________________________________________________ +Any IdlReflectionServiceImpl::getByHierarchicalName( const OUString & rName ) + throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException) +{ + Any aRet( _aElements.getValue( rName ) ); + if (! aRet.hasValue()) + { + // first look for constants exclusivly! + aRet = _xTDMgr->getByHierarchicalName( rName ); + if (aRet.getValueTypeClass() == TypeClass_INTERFACE) // if no constant, + // i.e. XTypeDescription for a type + { + // type retrieved from tdmgr + OSL_ASSERT( (*(Reference< XInterface > *)aRet.getValue())->queryInterface( + ::getCppuType( (const Reference< XTypeDescription > *)0 ) ).hasValue() ); + + // if you are interested in a type then CALL forName()!!! + // this way is NOT recommended for types, because this method looks for constants first + + // if td manager found some type, it will be in the cache (hopefully.. we just got it) + // so the second retrieving via c typelib callback chain should succeed... + + // try to get _type_ by name + typelib_TypeDescription * pTD = 0; + typelib_typedescription_getByName( &pTD, rName.pData ); + + aRet.clear(); // kick XTypeDescription interface + + if (pTD) + { + Reference< XIdlClass > xIdlClass( constructClass( pTD ) ); + aRet.setValue( &xIdlClass, ::getCppuType( (const Reference< XIdlClass > *)0 ) ); + typelib_typedescription_release( pTD ); + } + } + // else is constant + + // update + if (aRet.hasValue()) + _aElements.setValue( rName, aRet ); + else + { + throw NoSuchElementException( rName, Reference< XInterface >() ); + } + } + return aRet; +} +//__________________________________________________________________________________________________ +sal_Bool IdlReflectionServiceImpl::hasByHierarchicalName( const OUString & rName ) + throw(::com::sun::star::uno::RuntimeException) +{ + try + { + return getByHierarchicalName( rName ).hasValue(); + } + catch (NoSuchElementException &) + { + } + return sal_False; +} + +//__________________________________________________________________________________________________ +Reference< XIdlClass > IdlReflectionServiceImpl::forType( typelib_TypeDescription * pTypeDescr ) + throw(::com::sun::star::uno::RuntimeException) +{ + Reference< XIdlClass > xRet; + OUString aName( pTypeDescr->pTypeName ); + Any aAny( _aElements.getValue( aName ) ); + + if (aAny.hasValue()) + { + if (aAny.getValueTypeClass() == TypeClass_INTERFACE) + xRet = *(const Reference< XIdlClass > *)aAny.getValue(); + } + else + { + if (pTypeDescr && (xRet = constructClass( pTypeDescr )).is()) + _aElements.setValue( aName, makeAny( xRet ) ); // update + } + + return xRet; +} +//__________________________________________________________________________________________________ +Reference< XIdlClass > IdlReflectionServiceImpl::forType( typelib_TypeDescriptionReference * pRef ) + throw(::com::sun::star::uno::RuntimeException) +{ + typelib_TypeDescription * pTD = 0; + TYPELIB_DANGER_GET( &pTD, pRef ); + if (pTD) + { + Reference< XIdlClass > xRet = forType( pTD ); + TYPELIB_DANGER_RELEASE( pTD ); + return xRet; + } + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("IdlReflectionServiceImpl::forType() failed!") ), + (XWeak *)(OWeakObject *)this ); +} + +//__________________________________________________________________________________________________ +const Mapping & IdlReflectionServiceImpl::getCpp2Uno() + throw(::com::sun::star::uno::RuntimeException) +{ + if (! _aCpp2Uno.is()) + { + MutexGuard aGuard( getMutexAccess() ); + if (! _aCpp2Uno.is()) + { + _aCpp2Uno = Mapping( + OUString( RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME) ), + OUString( RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO) ) ); + OSL_ENSURE( _aCpp2Uno.is(), "### cannot get c++ to uno mapping!" ); + if (! _aCpp2Uno.is()) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get c++ to uno mapping!") ), + (XWeak *)(OWeakObject *)this ); + } + } + } + return _aCpp2Uno; +} +//__________________________________________________________________________________________________ +const Mapping & IdlReflectionServiceImpl::getUno2Cpp() + throw(::com::sun::star::uno::RuntimeException) +{ + if (! _aUno2Cpp.is()) + { + MutexGuard aGuard( getMutexAccess() ); + if (! _aUno2Cpp.is()) + { + _aUno2Cpp = Mapping( + OUString( RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO) ), + OUString( RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME) ) ); + OSL_ENSURE( _aUno2Cpp.is(), "### cannot get uno to c++ mapping!" ); + if (! _aUno2Cpp.is()) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get uno to c++ mapping!") ), + (XWeak *)(OWeakObject *)this ); + } + } + } + return _aUno2Cpp; +} +//__________________________________________________________________________________________________ +uno_Interface * IdlReflectionServiceImpl::mapToUno( + const Any & rObj, typelib_InterfaceTypeDescription * pTo ) + throw(::com::sun::star::uno::RuntimeException) +{ + Reference< XInterface > xObj; + if (extract( rObj, pTo, xObj, this )) + return (uno_Interface *)getCpp2Uno().mapInterface( xObj.get(), pTo ); + + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal object given!") ), + (XWeak *)(OWeakObject *)this ); +} + +//================================================================================================== +Reference< XInterface > SAL_CALL IdlReflectionServiceImpl_create( + const Reference< XComponentContext > & xContext ) + throw(::com::sun::star::uno::Exception) +{ + return Reference< XInterface >( (XWeak *)(OWeakObject *)new IdlReflectionServiceImpl( xContext ) ); +} + +} + + +//################################################################################################## +//################################################################################################## +//################################################################################################## + +using namespace stoc_corefl; + +static struct ImplementationEntry g_entries[] = +{ + { + IdlReflectionServiceImpl_create, core_getImplementationName, + core_getSupportedServiceNames, createSingleComponentFactory, + &g_moduleCount.modCnt , 0 + }, + { 0, 0, 0, 0, 0, 0 } +}; + +extern "C" +{ +sal_Bool SAL_CALL component_canUnload( TimeValue *pTime ) +{ + return g_moduleCount.canUnload( &g_moduleCount , pTime ); +} + +//================================================================================================== +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} +//================================================================================================== +void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) +{ + return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries ); +} +} diff --git a/stoc/source/corereflection/crenum.cxx b/stoc/source/corereflection/crenum.cxx new file mode 100644 index 000000000000..174e177080fe --- /dev/null +++ b/stoc/source/corereflection/crenum.cxx @@ -0,0 +1,247 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include "base.hxx" + +namespace stoc_corefl +{ + +//================================================================================================== +class IdlEnumFieldImpl + : public IdlMemberImpl + , public XIdlField + , public XIdlField2 +{ + sal_Int32 _nValue; + +public: + IdlEnumFieldImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName, + typelib_TypeDescription * pTypeDescr, sal_Int32 nValue ) + : IdlMemberImpl( pReflection, rName, pTypeDescr, pTypeDescr ) + , _nValue( nValue ) + {} + virtual ~IdlEnumFieldImpl(); + + // XInterface + virtual Any SAL_CALL queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + // XTypeProvider + virtual Sequence< Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // XIdlMember + virtual Reference< XIdlClass > SAL_CALL getDeclaringClass() throw(::com::sun::star::uno::RuntimeException); + virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); + // XIdlField + virtual Reference< XIdlClass > SAL_CALL getType() throw(::com::sun::star::uno::RuntimeException); + virtual FieldAccessMode SAL_CALL getAccessMode() throw(::com::sun::star::uno::RuntimeException); + virtual Any SAL_CALL get( const Any & rObj ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL set( const Any & rObj, const Any & rValue ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException); + // XIdlField2: getType, getAccessMode and get are equal to XIdlField + virtual void SAL_CALL set( Any & rObj, const Any & rValue ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException); +}; +//__________________________________________________________________________________________________ +IdlEnumFieldImpl::~IdlEnumFieldImpl() +{ +} + +// XInterface +//__________________________________________________________________________________________________ +Any IdlEnumFieldImpl::queryInterface( const Type & rType ) + throw(::com::sun::star::uno::RuntimeException) +{ + Any aRet( ::cppu::queryInterface( rType, + static_cast< XIdlField * >( this ), + static_cast< XIdlField2 * >( this ) ) ); + return (aRet.hasValue() ? aRet : IdlMemberImpl::queryInterface( rType )); +} +//__________________________________________________________________________________________________ +void IdlEnumFieldImpl::acquire() throw() +{ + IdlMemberImpl::acquire(); +} +//__________________________________________________________________________________________________ +void IdlEnumFieldImpl::release() throw() +{ + IdlMemberImpl::release(); +} + +// XTypeProvider +//__________________________________________________________________________________________________ +Sequence< Type > IdlEnumFieldImpl::getTypes() + throw (::com::sun::star::uno::RuntimeException) +{ + static OTypeCollection * s_pTypes = 0; + if (! s_pTypes) + { + MutexGuard aGuard( getMutexAccess() ); + if (! s_pTypes) + { + static OTypeCollection s_aTypes( + ::getCppuType( (const Reference< XIdlField2 > *)0 ), + ::getCppuType( (const Reference< XIdlField > *)0 ), + IdlMemberImpl::getTypes() ); + s_pTypes = &s_aTypes; + } + } + return s_pTypes->getTypes(); +} +//__________________________________________________________________________________________________ +Sequence< sal_Int8 > IdlEnumFieldImpl::getImplementationId() + throw (::com::sun::star::uno::RuntimeException) +{ + static OImplementationId * s_pId = 0; + if (! s_pId) + { + MutexGuard aGuard( getMutexAccess() ); + if (! s_pId) + { + static OImplementationId s_aId; + s_pId = &s_aId; + } + } + return s_pId->getImplementationId(); +} + +// XIdlMember +//__________________________________________________________________________________________________ +Reference< XIdlClass > IdlEnumFieldImpl::getDeclaringClass() + throw(::com::sun::star::uno::RuntimeException) +{ + return IdlMemberImpl::getDeclaringClass(); +} +//__________________________________________________________________________________________________ +OUString IdlEnumFieldImpl::getName() + throw(::com::sun::star::uno::RuntimeException) +{ + return IdlMemberImpl::getName(); +} + +// XIdlField +//__________________________________________________________________________________________________ +Reference< XIdlClass > IdlEnumFieldImpl::getType() + throw(::com::sun::star::uno::RuntimeException) +{ + return getDeclaringClass(); +} +//__________________________________________________________________________________________________ +FieldAccessMode IdlEnumFieldImpl::getAccessMode() + throw(::com::sun::star::uno::RuntimeException) +{ + return FieldAccessMode_READONLY; +} +//__________________________________________________________________________________________________ +Any IdlEnumFieldImpl::get( const Any & ) + throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + return Any( &_nValue, getTypeDescr() ); +} +//__________________________________________________________________________________________________ +void IdlEnumFieldImpl::set( const Any &, const Any & ) + throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException) +{ + throw IllegalAccessException( + OUString( RTL_CONSTASCII_USTRINGPARAM("enum field is constant!") ), + (XWeak *)(OWeakObject *)this ); +} +//__________________________________________________________________________________________________ +void IdlEnumFieldImpl::set( Any &, const Any & ) + throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException) +{ + throw IllegalAccessException( + OUString( RTL_CONSTASCII_USTRINGPARAM("enum field is constant!") ), + (XWeak *)(OWeakObject *)this ); +} + +//################################################################################################## +//################################################################################################## +//################################################################################################## + + +//__________________________________________________________________________________________________ +EnumIdlClassImpl::~EnumIdlClassImpl() +{ + delete _pFields; +} + +// IdlClassImpl modifications +//__________________________________________________________________________________________________ +Reference< XIdlField > EnumIdlClassImpl::getField( const OUString & rName ) + throw(::com::sun::star::uno::RuntimeException) +{ + if (! _pFields) + getFields(); // init members + + const OUString2Field::const_iterator iFind( _aName2Field.find( rName ) ); + if (iFind != _aName2Field.end()) + return (*iFind).second; + else + return Reference< XIdlField >(); +} +//__________________________________________________________________________________________________ +Sequence< Reference< XIdlField > > EnumIdlClassImpl::getFields() + throw(::com::sun::star::uno::RuntimeException) +{ + if (! _pFields) + { + MutexGuard aGuard( getMutexAccess() ); + if (! _pFields) + { + sal_Int32 nFields = getTypeDescr()->nEnumValues; + Sequence< Reference< XIdlField > > * pFields = + new Sequence< Reference< XIdlField > >( nFields ); + Reference< XIdlField > * pSeq = pFields->getArray(); + + while (nFields--) + { + OUString aName( getTypeDescr()->ppEnumNames[nFields] ); + _aName2Field[aName] = pSeq[nFields] = new IdlEnumFieldImpl( + getReflection(), aName, IdlClassImpl::getTypeDescr(), getTypeDescr()->pEnumValues[nFields] ); + } + + _pFields = pFields; + } + } + return *_pFields; +} +//__________________________________________________________________________________________________ +void EnumIdlClassImpl::createObject( Any & rObj ) + throw(::com::sun::star::uno::RuntimeException) +{ + sal_Int32 eVal = + ((typelib_EnumTypeDescription *)IdlClassImpl::getTypeDescr())->nDefaultEnumValue; + rObj.setValue( &eVal, IdlClassImpl::getTypeDescr() ); +} + +} + + diff --git a/stoc/source/corereflection/criface.cxx b/stoc/source/corereflection/criface.cxx new file mode 100644 index 000000000000..95d9990257f5 --- /dev/null +++ b/stoc/source/corereflection/criface.cxx @@ -0,0 +1,993 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include <sal/config.h> +#ifdef SAL_UNX +#include <sal/alloca.h> +#endif +#if !(defined(MACOSX) || defined(FREEBSD)) +#include <malloc.h> +#endif +#include <rtl/alloc.h> +#include <typelib/typedescription.hxx> +#include <uno/data.h> + +#include "base.hxx" + +#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "cppuhelper/exc_hlp.hxx" + +namespace stoc_corefl +{ + +//================================================================================================== +class IdlAttributeFieldImpl + : public IdlMemberImpl + , public XIdlField + , public XIdlField2 +{ +public: + typelib_InterfaceAttributeTypeDescription * getAttributeTypeDescr() + { return (typelib_InterfaceAttributeTypeDescription *)getTypeDescr(); } + + IdlAttributeFieldImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName, + typelib_TypeDescription * pTypeDescr, typelib_TypeDescription * pDeclTypeDescr ) + : IdlMemberImpl( pReflection, rName, pTypeDescr, pDeclTypeDescr ) + {} + + // XInterface + virtual Any SAL_CALL queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + // XTypeProvider + virtual Sequence< Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // XIdlMember + virtual Reference< XIdlClass > SAL_CALL getDeclaringClass() throw(::com::sun::star::uno::RuntimeException); + virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); + // XIdlField + virtual Reference< XIdlClass > SAL_CALL getType() throw(::com::sun::star::uno::RuntimeException); + virtual FieldAccessMode SAL_CALL getAccessMode() throw(::com::sun::star::uno::RuntimeException); + virtual Any SAL_CALL get( const Any & rObj ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL set( const Any & rObj, const Any & rValue ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException); + // XIdlField2: getType, getAccessMode and get are equal to XIdlField + virtual void SAL_CALL set( Any & rObj, const Any & rValue ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException); + +private: + void checkException( + uno_Any * exception, Reference< XInterface > const & context); +}; + +// XInterface +//__________________________________________________________________________________________________ +Any IdlAttributeFieldImpl::queryInterface( const Type & rType ) + throw(::com::sun::star::uno::RuntimeException) +{ + Any aRet( ::cppu::queryInterface( rType, + static_cast< XIdlField * >( this ), + static_cast< XIdlField2 * >( this ) ) ); + return (aRet.hasValue() ? aRet : IdlMemberImpl::queryInterface( rType )); +} +//__________________________________________________________________________________________________ +void IdlAttributeFieldImpl::acquire() throw() +{ + IdlMemberImpl::acquire(); +} +//__________________________________________________________________________________________________ +void IdlAttributeFieldImpl::release() throw() +{ + IdlMemberImpl::release(); +} + +// XTypeProvider +//__________________________________________________________________________________________________ +Sequence< Type > IdlAttributeFieldImpl::getTypes() + throw (::com::sun::star::uno::RuntimeException) +{ + static OTypeCollection * s_pTypes = 0; + if (! s_pTypes) + { + MutexGuard aGuard( getMutexAccess() ); + if (! s_pTypes) + { + static OTypeCollection s_aTypes( + ::getCppuType( (const Reference< XIdlField2 > *)0 ), + ::getCppuType( (const Reference< XIdlField > *)0 ), + IdlMemberImpl::getTypes() ); + s_pTypes = &s_aTypes; + } + } + return s_pTypes->getTypes(); +} +//__________________________________________________________________________________________________ +Sequence< sal_Int8 > IdlAttributeFieldImpl::getImplementationId() + throw (::com::sun::star::uno::RuntimeException) +{ + static OImplementationId * s_pId = 0; + if (! s_pId) + { + MutexGuard aGuard( getMutexAccess() ); + if (! s_pId) + { + static OImplementationId s_aId; + s_pId = &s_aId; + } + } + return s_pId->getImplementationId(); +} + +// XIdlMember +//__________________________________________________________________________________________________ +Reference< XIdlClass > IdlAttributeFieldImpl::getDeclaringClass() + throw(::com::sun::star::uno::RuntimeException) +{ + if (! _xDeclClass.is()) + { + MutexGuard aGuard( getMutexAccess() ); + if (! _xDeclClass.is()) + { + rtl::OUString aName(getAttributeTypeDescr()->aBase.aBase.pTypeName); + sal_Int32 i = aName.indexOf(':'); + OSL_ASSERT(i >= 0); + _xDeclClass = getReflection()->forName(aName.copy(0, i)); + } + } + return _xDeclClass; +} +//__________________________________________________________________________________________________ +OUString IdlAttributeFieldImpl::getName() + throw(::com::sun::star::uno::RuntimeException) +{ + return IdlMemberImpl::getName(); +} + +// XIdlField +//__________________________________________________________________________________________________ +Reference< XIdlClass > IdlAttributeFieldImpl::getType() + throw(::com::sun::star::uno::RuntimeException) +{ + return getReflection()->forType( + getAttributeTypeDescr()->pAttributeTypeRef ); +} +//__________________________________________________________________________________________________ +FieldAccessMode IdlAttributeFieldImpl::getAccessMode() + throw(::com::sun::star::uno::RuntimeException) +{ + return (((typelib_InterfaceAttributeTypeDescription *)getAttributeTypeDescr())->bReadOnly + ? FieldAccessMode_READONLY : FieldAccessMode_READWRITE); +} +//__________________________________________________________________________________________________ +Any IdlAttributeFieldImpl::get( const Any & rObj ) + throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + uno_Interface * pUnoI = getReflection()->mapToUno( + rObj, (typelib_InterfaceTypeDescription *)getDeclTypeDescr() ); + OSL_ENSURE( pUnoI, "### illegal destination object given!" ); + if (pUnoI) + { + TypeDescription aTD( getAttributeTypeDescr()->pAttributeTypeRef ); + typelib_TypeDescription * pTD = aTD.get(); + + uno_Any aExc; + uno_Any * pExc = &aExc; + void * pReturn = alloca( pTD->nSize ); + + (*pUnoI->pDispatcher)( pUnoI, getTypeDescr(), pReturn, 0, &pExc ); + (*pUnoI->release)( pUnoI ); + + checkException( + pExc, + *static_cast< Reference< XInterface > const * >(rObj.getValue())); + Any aRet; + uno_any_destruct( + &aRet, reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + uno_any_constructAndConvert( &aRet, pReturn, pTD, getReflection()->getUno2Cpp().get() ); + uno_destructData( pReturn, pTD, 0 ); + return aRet; + } + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal object given!") ), + (XWeak *)(OWeakObject *)this, 0 ); +} +//__________________________________________________________________________________________________ +void IdlAttributeFieldImpl::set( Any & rObj, const Any & rValue ) + throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException) +{ + if (getAttributeTypeDescr()->bReadOnly) + { + throw IllegalAccessException( + OUString( RTL_CONSTASCII_USTRINGPARAM("cannot set readonly attribute!") ), + (XWeak *)(OWeakObject *)this ); + } + + uno_Interface * pUnoI = getReflection()->mapToUno( + rObj, (typelib_InterfaceTypeDescription *)getDeclTypeDescr() ); + OSL_ENSURE( pUnoI, "### illegal destination object given!" ); + if (pUnoI) + { + TypeDescription aTD( getAttributeTypeDescr()->pAttributeTypeRef ); + typelib_TypeDescription * pTD = aTD.get(); + + // construct uno value to be set + void * pArgs[1]; + void * pArg = pArgs[0] = alloca( pTD->nSize ); + + sal_Bool bAssign; + if (pTD->eTypeClass == typelib_TypeClass_ANY) + { + uno_copyAndConvertData( pArg, SAL_CONST_CAST( Any *, &rValue ), + pTD, getReflection()->getCpp2Uno().get() ); + bAssign = sal_True; + } + else if (typelib_typedescriptionreference_equals( rValue.getValueTypeRef(), pTD->pWeakRef )) + { + uno_copyAndConvertData( pArg, SAL_CONST_CAST( void *, rValue.getValue() ), + pTD, getReflection()->getCpp2Uno().get() ); + bAssign = sal_True; + } + else if (pTD->eTypeClass == typelib_TypeClass_INTERFACE) + { + Reference< XInterface > xObj; + bAssign = extract( + rValue, (typelib_InterfaceTypeDescription *)pTD, xObj, + getReflection() ); + if (bAssign) + { + *(void **)pArg = getReflection()->getCpp2Uno().mapInterface( + xObj.get(), (typelib_InterfaceTypeDescription *)pTD ); + } + } + else + { + typelib_TypeDescription * pValueTD = 0; + TYPELIB_DANGER_GET( &pValueTD, rValue.getValueTypeRef() ); + // construct temp uno val to do proper assignment: todo opt + void * pTemp = alloca( pValueTD->nSize ); + uno_copyAndConvertData( + pTemp, (void *)rValue.getValue(), pValueTD, getReflection()->getCpp2Uno().get() ); + uno_constructData( + pArg, pTD ); + // assignment does simple conversion + bAssign = uno_assignData( + pArg, pTD, pTemp, pValueTD, 0, 0, 0 ); + uno_destructData( + pTemp, pValueTD, 0 ); + TYPELIB_DANGER_RELEASE( pValueTD ); + } + + if (bAssign) + { + uno_Any aExc; + uno_Any * pExc = &aExc; + (*pUnoI->pDispatcher)( pUnoI, getTypeDescr(), 0, pArgs, &pExc ); + (*pUnoI->release)( pUnoI ); + + uno_destructData( pArg, pTD, 0 ); + checkException( + pExc, + *static_cast< Reference< XInterface > const * >( + rObj.getValue())); + return; + } + (*pUnoI->release)( pUnoI ); + + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal value given!") ), + *(const Reference< XInterface > *)rObj.getValue(), 1 ); + } + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal destination object given!") ), + (XWeak *)(OWeakObject *)this, 0 ); +} +//__________________________________________________________________________________________________ +void IdlAttributeFieldImpl::set( const Any & rObj, const Any & rValue ) + throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::IllegalAccessException, ::com::sun::star::uno::RuntimeException) +{ + IdlAttributeFieldImpl::set( const_cast< Any & >( rObj ), rValue ); +} + +void IdlAttributeFieldImpl::checkException( + uno_Any * exception, Reference< XInterface > const & context) +{ + if (exception != 0) { + Any e; + uno_any_destruct(&e, reinterpret_cast< uno_ReleaseFunc >(cpp_release)); + uno_type_any_constructAndConvert( + &e, exception->pData, exception->pType, + getReflection()->getUno2Cpp().get()); + uno_any_destruct(exception, 0); + if (e.isExtractableTo( + getCppuType(static_cast< RuntimeException const * >(0)))) + { + cppu::throwException(e); + } else { + throw WrappedTargetRuntimeException( + OUString( + RTL_CONSTASCII_USTRINGPARAM( + "non-RuntimeException occured when accessing an" + " interface type attribute")), + context, e); + } + } +} + +//################################################################################################## +//################################################################################################## +//################################################################################################## + + +//================================================================================================== +class IdlInterfaceMethodImpl + : public IdlMemberImpl + , public XIdlMethod +{ + Sequence< Reference< XIdlClass > > * _pExceptionTypes; + Sequence< Reference< XIdlClass > > * _pParamTypes; + Sequence< ParamInfo > * _pParamInfos; + +public: + typelib_InterfaceMethodTypeDescription * getMethodTypeDescr() + { return (typelib_InterfaceMethodTypeDescription *)getTypeDescr(); } + + IdlInterfaceMethodImpl( IdlReflectionServiceImpl * pReflection, const OUString & rName, + typelib_TypeDescription * pTypeDescr, typelib_TypeDescription * pDeclTypeDescr ) + : IdlMemberImpl( pReflection, rName, pTypeDescr, pDeclTypeDescr ) + , _pExceptionTypes( 0 ) + , _pParamTypes( 0 ) + , _pParamInfos( 0 ) + {} + virtual ~IdlInterfaceMethodImpl(); + + // XInterface + virtual Any SAL_CALL queryInterface( const Type & rType ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + // XTypeProvider + virtual Sequence< Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // XIdlMember + virtual Reference< XIdlClass > SAL_CALL getDeclaringClass() throw(::com::sun::star::uno::RuntimeException); + virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); + // XIdlMethod + virtual Reference< XIdlClass > SAL_CALL getReturnType() throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< Reference< XIdlClass > > SAL_CALL getParameterTypes() throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< ParamInfo > SAL_CALL getParameterInfos() throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< Reference< XIdlClass > > SAL_CALL getExceptionTypes() throw(::com::sun::star::uno::RuntimeException); + virtual MethodMode SAL_CALL getMode() throw(::com::sun::star::uno::RuntimeException); + virtual Any SAL_CALL invoke( const Any & rObj, Sequence< Any > & rArgs ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::reflection::InvocationTargetException, ::com::sun::star::uno::RuntimeException); +}; +//__________________________________________________________________________________________________ +IdlInterfaceMethodImpl::~IdlInterfaceMethodImpl() +{ + delete _pParamInfos; + delete _pParamTypes; + delete _pExceptionTypes; +} + +// XInterface +//__________________________________________________________________________________________________ +Any IdlInterfaceMethodImpl::queryInterface( const Type & rType ) + throw(::com::sun::star::uno::RuntimeException) +{ + Any aRet( ::cppu::queryInterface( rType, static_cast< XIdlMethod * >( this ) ) ); + return (aRet.hasValue() ? aRet : IdlMemberImpl::queryInterface( rType )); +} +//__________________________________________________________________________________________________ +void IdlInterfaceMethodImpl::acquire() throw() +{ + IdlMemberImpl::acquire(); +} +//__________________________________________________________________________________________________ +void IdlInterfaceMethodImpl::release() throw() +{ + IdlMemberImpl::release(); +} + +// XTypeProvider +//__________________________________________________________________________________________________ +Sequence< Type > IdlInterfaceMethodImpl::getTypes() + throw (::com::sun::star::uno::RuntimeException) +{ + static OTypeCollection * s_pTypes = 0; + if (! s_pTypes) + { + MutexGuard aGuard( getMutexAccess() ); + if (! s_pTypes) + { + static OTypeCollection s_aTypes( + ::getCppuType( (const Reference< XIdlMethod > *)0 ), + IdlMemberImpl::getTypes() ); + s_pTypes = &s_aTypes; + } + } + return s_pTypes->getTypes(); +} +//__________________________________________________________________________________________________ +Sequence< sal_Int8 > IdlInterfaceMethodImpl::getImplementationId() + throw (::com::sun::star::uno::RuntimeException) +{ + static OImplementationId * s_pId = 0; + if (! s_pId) + { + MutexGuard aGuard( getMutexAccess() ); + if (! s_pId) + { + static OImplementationId s_aId; + s_pId = &s_aId; + } + } + return s_pId->getImplementationId(); +} + +// XIdlMember +//__________________________________________________________________________________________________ +Reference< XIdlClass > IdlInterfaceMethodImpl::getDeclaringClass() + throw(::com::sun::star::uno::RuntimeException) +{ + if (! _xDeclClass.is()) + { + MutexGuard aGuard( getMutexAccess() ); + if (! _xDeclClass.is()) + { + rtl::OUString aName(getMethodTypeDescr()->aBase.aBase.pTypeName); + sal_Int32 i = aName.indexOf(':'); + OSL_ASSERT(i >= 0); + _xDeclClass = getReflection()->forName(aName.copy(0, i)); + } + } + return _xDeclClass; +} +//__________________________________________________________________________________________________ +OUString IdlInterfaceMethodImpl::getName() + throw(::com::sun::star::uno::RuntimeException) +{ + return IdlMemberImpl::getName(); +} + +// XIdlMethod +//__________________________________________________________________________________________________ +Reference< XIdlClass > SAL_CALL IdlInterfaceMethodImpl::getReturnType() + throw(::com::sun::star::uno::RuntimeException) +{ + return getReflection()->forType( getMethodTypeDescr()->pReturnTypeRef ); +} +//__________________________________________________________________________________________________ +Sequence< Reference< XIdlClass > > IdlInterfaceMethodImpl::getExceptionTypes() + throw(::com::sun::star::uno::RuntimeException) +{ + if (! _pExceptionTypes) + { + MutexGuard aGuard( getMutexAccess() ); + if (! _pExceptionTypes) + { + sal_Int32 nExc = getMethodTypeDescr()->nExceptions; + Sequence< Reference< XIdlClass > > * pTempExceptionTypes = + new Sequence< Reference< XIdlClass > >( nExc ); + Reference< XIdlClass > * pExceptionTypes = pTempExceptionTypes->getArray(); + + typelib_TypeDescriptionReference ** ppExc = + getMethodTypeDescr()->ppExceptions; + IdlReflectionServiceImpl * pRefl = getReflection(); + + while (nExc--) + pExceptionTypes[nExc] = pRefl->forType( ppExc[nExc] ); + + _pExceptionTypes = pTempExceptionTypes; + } + } + return *_pExceptionTypes; +} +//__________________________________________________________________________________________________ +Sequence< Reference< XIdlClass > > IdlInterfaceMethodImpl::getParameterTypes() + throw(::com::sun::star::uno::RuntimeException) +{ + if (! _pParamTypes) + { + MutexGuard aGuard( getMutexAccess() ); + if (! _pParamTypes) + { + sal_Int32 nParams = getMethodTypeDescr()->nParams; + Sequence< Reference< XIdlClass > > * pTempParamTypes = + new Sequence< Reference< XIdlClass > >( nParams ); + Reference< XIdlClass > * pParamTypes = pTempParamTypes->getArray(); + + typelib_MethodParameter * pTypelibParams = + getMethodTypeDescr()->pParams; + IdlReflectionServiceImpl * pRefl = getReflection(); + + while (nParams--) + pParamTypes[nParams] = pRefl->forType( pTypelibParams[nParams].pTypeRef ); + + _pParamTypes = pTempParamTypes; + } + } + return *_pParamTypes; +} +//__________________________________________________________________________________________________ +Sequence< ParamInfo > IdlInterfaceMethodImpl::getParameterInfos() + throw(::com::sun::star::uno::RuntimeException) +{ + if (! _pParamInfos) + { + MutexGuard aGuard( getMutexAccess() ); + if (! _pParamInfos) + { + sal_Int32 nParams = getMethodTypeDescr()->nParams; + Sequence< ParamInfo > * pTempParamInfos = new Sequence< ParamInfo >( nParams ); + ParamInfo * pParamInfos = pTempParamInfos->getArray(); + + typelib_MethodParameter * pTypelibParams = + getMethodTypeDescr()->pParams; + + if (_pParamTypes) // use param types + { + const Reference< XIdlClass > * pParamTypes = _pParamTypes->getConstArray(); + + while (nParams--) + { + const typelib_MethodParameter & rParam = pTypelibParams[nParams]; + ParamInfo & rInfo = pParamInfos[nParams]; + rInfo.aName = rParam.pName; + if (rParam.bIn) + rInfo.aMode = (rParam.bOut ? ParamMode_INOUT : ParamMode_IN); + else + rInfo.aMode = ParamMode_OUT; + rInfo.aType = pParamTypes[nParams]; + } + } + else // make also param types sequence if not already initialized + { + Sequence< Reference< XIdlClass > > * pTempParamTypes = + new Sequence< Reference< XIdlClass > >( nParams ); + Reference< XIdlClass > * pParamTypes = pTempParamTypes->getArray(); + + IdlReflectionServiceImpl * pRefl = getReflection(); + + while (nParams--) + { + const typelib_MethodParameter & rParam = pTypelibParams[nParams]; + ParamInfo & rInfo = pParamInfos[nParams]; + rInfo.aName = rParam.pName; + if (rParam.bIn) + rInfo.aMode = (rParam.bOut ? ParamMode_INOUT : ParamMode_IN); + else + rInfo.aMode = ParamMode_OUT; + rInfo.aType = pParamTypes[nParams] = pRefl->forType( rParam.pTypeRef ); + } + + _pParamTypes = pTempParamTypes; + } + + _pParamInfos = pTempParamInfos; + } + } + return *_pParamInfos; +} +//__________________________________________________________________________________________________ +MethodMode SAL_CALL IdlInterfaceMethodImpl::getMode() + throw(::com::sun::star::uno::RuntimeException) +{ + return + getMethodTypeDescr()->bOneWay ? MethodMode_ONEWAY : MethodMode_TWOWAY; +} +//__________________________________________________________________________________________________ +Any SAL_CALL IdlInterfaceMethodImpl::invoke( const Any & rObj, Sequence< Any > & rArgs ) + throw(::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::reflection::InvocationTargetException, + ::com::sun::star::uno::RuntimeException) +{ + if (rObj.getValueTypeClass() == TypeClass_INTERFACE) + { + // acquire()/ release() + if (rtl_ustr_ascii_compare( getTypeDescr()->pTypeName->buffer, + "com.sun.star.uno.XInterface::acquire" ) == 0) + { + (*(const Reference< XInterface > *)rObj.getValue())->acquire(); + return Any(); + } + else if (rtl_ustr_ascii_compare( getTypeDescr()->pTypeName->buffer, + "com.sun.star.uno.XInterface::release" ) == 0) + { + (*(const Reference< XInterface > *)rObj.getValue())->release(); + return Any(); + } + } + + uno_Interface * pUnoI = getReflection()->mapToUno( + rObj, (typelib_InterfaceTypeDescription *)getDeclTypeDescr() ); + OSL_ENSURE( pUnoI, "### illegal destination object given!" ); + if (pUnoI) + { + sal_Int32 nParams = getMethodTypeDescr()->nParams; + if (rArgs.getLength() != nParams) + { + (*pUnoI->release)( pUnoI ); + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("arguments len differ!") ), + *(const Reference< XInterface > *)rObj.getValue(), 1 ); + } + + Any * pCppArgs = rArgs.getArray(); + typelib_MethodParameter * pParams = getMethodTypeDescr()->pParams; + typelib_TypeDescription * pReturnType = 0; + TYPELIB_DANGER_GET( + &pReturnType, getMethodTypeDescr()->pReturnTypeRef ); + + void * pUnoReturn = alloca( pReturnType->nSize ); + void ** ppUnoArgs = (void **)alloca( sizeof(void *) * nParams *2 ); + typelib_TypeDescription ** ppParamTypes = (typelib_TypeDescription **)(ppUnoArgs + nParams); + + // convert arguments + for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) + { + ppParamTypes[nPos] = 0; + TYPELIB_DANGER_GET( ppParamTypes + nPos, pParams[nPos].pTypeRef ); + typelib_TypeDescription * pTD = ppParamTypes[nPos]; + + ppUnoArgs[nPos] = alloca( pTD->nSize ); + if (pParams[nPos].bIn) + { + sal_Bool bAssign; + if (typelib_typedescriptionreference_equals( + pCppArgs[nPos].getValueTypeRef(), pTD->pWeakRef )) + { + uno_type_copyAndConvertData( + ppUnoArgs[nPos], (void *)pCppArgs[nPos].getValue(), + pCppArgs[nPos].getValueTypeRef(), getReflection()->getCpp2Uno().get() ); + bAssign = sal_True; + } + else if (pTD->eTypeClass == typelib_TypeClass_ANY) + { + uno_type_any_constructAndConvert( + (uno_Any *)ppUnoArgs[nPos], (void *)pCppArgs[nPos].getValue(), + pCppArgs[nPos].getValueTypeRef(), getReflection()->getCpp2Uno().get() ); + bAssign = sal_True; + } + else if (pTD->eTypeClass == typelib_TypeClass_INTERFACE) + { + Reference< XInterface > xDest; + bAssign = extract( + pCppArgs[nPos], (typelib_InterfaceTypeDescription *)pTD, + xDest, getReflection() ); + if (bAssign) + { + *(void **)ppUnoArgs[nPos] = getReflection()->getCpp2Uno().mapInterface( + xDest.get(), (typelib_InterfaceTypeDescription *)pTD ); + } + } + else + { + typelib_TypeDescription * pValueTD = 0; + TYPELIB_DANGER_GET( &pValueTD, pCppArgs[nPos].getValueTypeRef() ); + // construct temp uno val to do proper assignment: todo opt + void * pTemp = alloca( pValueTD->nSize ); + uno_copyAndConvertData( + pTemp, (void *)pCppArgs[nPos].getValue(), pValueTD, + getReflection()->getCpp2Uno().get() ); + uno_constructData( + ppUnoArgs[nPos], pTD ); + // assignment does simple conversion + bAssign = uno_assignData( + ppUnoArgs[nPos], pTD, pTemp, pValueTD, 0, 0, 0 ); + uno_destructData( + pTemp, pValueTD, 0 ); + TYPELIB_DANGER_RELEASE( pValueTD ); + } + + if (! bAssign) + { + IllegalArgumentException aExc( + OUString( RTL_CONSTASCII_USTRINGPARAM("cannot coerce argument type during corereflection call!") ), + *(const Reference< XInterface > *)rObj.getValue(), (sal_Int16)nPos ); + + // cleanup + while (nPos--) + { + if (pParams[nPos].bIn) + uno_destructData( ppUnoArgs[nPos], ppParamTypes[nPos], 0 ); + TYPELIB_DANGER_RELEASE( ppParamTypes[nPos] ); + } + TYPELIB_DANGER_RELEASE( pReturnType ); + (*pUnoI->release)( pUnoI ); + + throw aExc; + } + } + } + + uno_Any aUnoExc; + uno_Any * pUnoExc = &aUnoExc; + + (*pUnoI->pDispatcher)( + pUnoI, getTypeDescr(), pUnoReturn, ppUnoArgs, &pUnoExc ); + (*pUnoI->release)( pUnoI ); + + Any aRet; + if (pUnoExc) + { + // cleanup + while (nParams--) + { + if (pParams[nParams].bIn) + uno_destructData( ppUnoArgs[nParams], ppParamTypes[nParams], 0 ); + TYPELIB_DANGER_RELEASE( ppParamTypes[nParams] ); + } + TYPELIB_DANGER_RELEASE( pReturnType ); + + InvocationTargetException aExc; + aExc.Context = *(const Reference< XInterface > *)rObj.getValue(); + aExc.Message = OUString( RTL_CONSTASCII_USTRINGPARAM("exception occured during invocation!") ); + uno_any_destruct( + &aExc.TargetException, + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + uno_type_copyAndConvertData( + &aExc.TargetException, pUnoExc, ::getCppuType( (const Any *)0 ).getTypeLibType(), + getReflection()->getUno2Cpp().get() ); + uno_any_destruct( pUnoExc, 0 ); + throw aExc; + } + else + { + // reconvert arguments and cleanup + while (nParams--) + { + if (pParams[nParams].bOut) // write back + { + uno_any_destruct( + &pCppArgs[nParams], + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + uno_any_constructAndConvert( + &pCppArgs[nParams], ppUnoArgs[nParams], ppParamTypes[nParams], + getReflection()->getUno2Cpp().get() ); + } + uno_destructData( ppUnoArgs[nParams], ppParamTypes[nParams], 0 ); + TYPELIB_DANGER_RELEASE( ppParamTypes[nParams] ); + } + uno_any_destruct( + &aRet, reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + uno_any_constructAndConvert( + &aRet, pUnoReturn, pReturnType, + getReflection()->getUno2Cpp().get() ); + uno_destructData( pUnoReturn, pReturnType, 0 ); + TYPELIB_DANGER_RELEASE( pReturnType ); + } + return aRet; + } + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("illegal destination object given!") ), + (XWeak *)(OWeakObject *)this, 0 ); +} + + +//################################################################################################## +//################################################################################################## +//################################################################################################## + + +//__________________________________________________________________________________________________ +InterfaceIdlClassImpl::~InterfaceIdlClassImpl() +{ + for ( sal_Int32 nPos = _nMethods + _nAttributes; nPos--; ) + typelib_typedescription_release( _pSortedMemberInit[nPos].second ); + + delete [] _pSortedMemberInit; +} + +//__________________________________________________________________________________________________ +Sequence< Reference< XIdlClass > > InterfaceIdlClassImpl::getSuperclasses() + throw(::com::sun::star::uno::RuntimeException) +{ + MutexGuard aGuard(getMutexAccess()); + if (_xSuperClasses.getLength() == 0) { + typelib_InterfaceTypeDescription * pType = getTypeDescr(); + _xSuperClasses.realloc(pType->nBaseTypes); + for (sal_Int32 i = 0; i < pType->nBaseTypes; ++i) { + _xSuperClasses[i] = getReflection()->forType( + &pType->ppBaseTypes[i]->aBase); + OSL_ASSERT(_xSuperClasses[i].is()); + } + } + return Sequence< Reference< XIdlClass > >(_xSuperClasses); +} +//__________________________________________________________________________________________________ +void InterfaceIdlClassImpl::initMembers() +{ + sal_Int32 nAll = getTypeDescr()->nAllMembers; + MemberInit * pSortedMemberInit = new MemberInit[nAll]; + typelib_TypeDescriptionReference ** ppAllMembers = getTypeDescr()->ppAllMembers; + + for ( sal_Int32 nPos = 0; nPos < nAll; ++nPos ) + { + sal_Int32 nIndex; + if (ppAllMembers[nPos]->eTypeClass == typelib_TypeClass_INTERFACE_METHOD) + { + // methods to front + nIndex = _nMethods; + ++_nMethods; + } + else + { + ++_nAttributes; + nIndex = (nAll - _nAttributes); + // attributes at the back + } + + typelib_TypeDescription * pTD = 0; + typelib_typedescriptionreference_getDescription( &pTD, ppAllMembers[nPos] ); + OSL_ENSURE( pTD, "### cannot get type description!" ); + pSortedMemberInit[nIndex].first = ((typelib_InterfaceMemberTypeDescription *)pTD)->pMemberName; + pSortedMemberInit[nIndex].second = pTD; + } + + _pSortedMemberInit = pSortedMemberInit; +} +//__________________________________________________________________________________________________ +sal_Bool InterfaceIdlClassImpl::isAssignableFrom( const Reference< XIdlClass > & xType ) + throw(::com::sun::star::uno::RuntimeException) +{ + if (xType.is() && xType->getTypeClass() == TypeClass_INTERFACE) + { + if (equals( xType )) + return sal_True; + else + { + const Sequence< Reference< XIdlClass > > & rSeq = xType->getSuperclasses(); + for (sal_Int32 i = 0; i < rSeq.getLength(); ++i) { + if (isAssignableFrom(rSeq[i])) { + return true; + } + } + } + } + return sal_False; +} +//__________________________________________________________________________________________________ +Uik InterfaceIdlClassImpl::getUik() + throw(::com::sun::star::uno::RuntimeException) +{ + return Uik(0, 0, 0, 0, 0); + // Uiks are deprecated and this function must not be called +} +//__________________________________________________________________________________________________ +Sequence< Reference< XIdlMethod > > InterfaceIdlClassImpl::getMethods() + throw(::com::sun::star::uno::RuntimeException) +{ + MutexGuard aGuard( getMutexAccess() ); + if (! _pSortedMemberInit) + initMembers(); + + // create methods sequence + Sequence< Reference< XIdlMethod > > aRet( _nMethods ); + Reference< XIdlMethod > * pRet = aRet.getArray(); + for ( sal_Int32 nPos = _nMethods; nPos--; ) + { + + /*_aName2Method[_pSortedMemberInit[nPos].first] = */pRet[nPos] = new IdlInterfaceMethodImpl( + getReflection(), _pSortedMemberInit[nPos].first, + _pSortedMemberInit[nPos].second, IdlClassImpl::getTypeDescr() ); + } + return aRet; +} +//__________________________________________________________________________________________________ +Sequence< Reference< XIdlField > > InterfaceIdlClassImpl::getFields() + throw(::com::sun::star::uno::RuntimeException) +{ + MutexGuard aGuard( getMutexAccess() ); + if (! _pSortedMemberInit) + initMembers(); + + // create fields sequence + Sequence< Reference< XIdlField > > aRet( _nAttributes ); + Reference< XIdlField > * pRet = aRet.getArray(); + for ( sal_Int32 nPos = _nAttributes; nPos--; ) + { + /*_aName2Field[_pSortedMemberInit[_nMethods+nPos].first] = */pRet[_nAttributes-nPos-1] = + new IdlAttributeFieldImpl( + getReflection(), _pSortedMemberInit[_nMethods+nPos].first, + _pSortedMemberInit[_nMethods+nPos].second, IdlClassImpl::getTypeDescr() ); + } + return aRet; +} +//__________________________________________________________________________________________________ +Reference< XIdlMethod > InterfaceIdlClassImpl::getMethod( const OUString & rName ) + throw(::com::sun::star::uno::RuntimeException) +{ + MutexGuard aGuard( getMutexAccess() ); + if (! _pSortedMemberInit) + initMembers(); + + Reference< XIdlMethod > xRet; + + // try weak map + const OUString2Method::const_iterator iFind( _aName2Method.find( rName ) ); + if (iFind != _aName2Method.end()) + xRet = (*iFind).second; // harden ref + + if (! xRet.is()) + { + for ( sal_Int32 nPos = _nMethods; nPos--; ) + { + if (_pSortedMemberInit[nPos].first == rName) + { + _aName2Method[rName] = xRet = new IdlInterfaceMethodImpl( + getReflection(), rName, + _pSortedMemberInit[nPos].second, IdlClassImpl::getTypeDescr() ); + break; + } + } + } + return xRet; +} +//__________________________________________________________________________________________________ +Reference< XIdlField > InterfaceIdlClassImpl::getField( const OUString & rName ) + throw(::com::sun::star::uno::RuntimeException) +{ + MutexGuard aGuard( getMutexAccess() ); + if (! _pSortedMemberInit) + initMembers(); + + Reference< XIdlField > xRet; + + // try weak map + const OUString2Field::const_iterator iFind( _aName2Field.find( rName ) ); + if (iFind != _aName2Field.end()) + xRet = (*iFind).second; // harden ref + + if (! xRet.is()) + { + for ( sal_Int32 nPos = _nAttributes; nPos--; ) + { + if (_pSortedMemberInit[_nMethods+nPos].first == rName) + { + _aName2Field[rName] = xRet = new IdlAttributeFieldImpl( + getReflection(), rName, + _pSortedMemberInit[_nMethods+nPos].second, IdlClassImpl::getTypeDescr() ); + break; + } + } + } + return xRet; +} +//__________________________________________________________________________________________________ +void InterfaceIdlClassImpl::createObject( Any & rObj ) + throw(::com::sun::star::uno::RuntimeException) +{ + // interfaces cannot be constructed + rObj.clear(); +} + +} + + diff --git a/stoc/source/corereflection/lrucache.hxx b/stoc/source/corereflection/lrucache.hxx new file mode 100644 index 000000000000..98c5faf4586d --- /dev/null +++ b/stoc/source/corereflection/lrucache.hxx @@ -0,0 +1,244 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _LRU_CACHE_HXX_ +#define _LRU_CACHE_HXX_ + +// __CACHE_DIAGNOSE forces cache size to 4 and works only for OUString keys +// #define __CACHE_DIAGNOSE 1 + +#include <osl/mutex.hxx> +#include "rtl/ustring.hxx" + +#include <hash_map> + +/** Implementation of a least recently used (lru) cache. + <br> + @author Daniel Boelzle +*/ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +class LRU_Cache +{ + struct CacheEntry + { + t_Key aKey; + t_Val aVal; + CacheEntry * pPred; + CacheEntry * pSucc; + }; + typedef ::std::hash_map< t_Key, CacheEntry *, t_KeyHash, t_KeyEqual > t_Key2Element; + + mutable ::osl::Mutex _aCacheMutex; + sal_Int32 _nCachedElements; + t_Key2Element _aKey2Element; + + CacheEntry * _pBlock; + mutable CacheEntry * _pHead; + mutable CacheEntry * _pTail; + inline void toFront( CacheEntry * pEntry ) const; + +public: + /** Constructor: + <br> + @param nCachedElements number of elements to be cached; default param set to 128 + */ + inline LRU_Cache( sal_Int32 nCachedElements = 128 ); + /** Destructor: releases all cached elements and keys. + <br> + */ + inline ~LRU_Cache(); + + /** Retrieves a value from the cache. Returns default constructed value, + if none was found. + <br> + @param rKey a key + @return value + */ + inline t_Val getValue( const t_Key & rKey ) const; + /** Sets a value to be cached for given key. + <br> + @param rKey a key + @param rValue a value + */ + inline void setValue( const t_Key & rKey, const t_Val & rValue ); + /** Tests whether a value is cached for given key. + <br> + @param rKey a key + @return true, if value is cached + */ + inline sal_Bool hasValue( const t_Key & rKey ) const; + /** Clears the cache, thus releasing all cached elements and keys. + <br> + */ + inline void clear(); +}; +//__________________________________________________________________________________________________ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +inline LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::LRU_Cache( sal_Int32 nCachedElements ) +#ifdef __CACHE_DIAGNOSE + : _nCachedElements( 4 ) +#else + : _nCachedElements( nCachedElements ) +#endif + , _pBlock( 0 ) +{ + if (_nCachedElements > 0) + { + _pBlock = new CacheEntry[_nCachedElements]; + _pHead = _pBlock; + _pTail = _pBlock + _nCachedElements -1; + for ( sal_Int32 nPos = _nCachedElements; nPos--; ) + { + _pBlock[nPos].pPred = _pBlock + nPos -1; + _pBlock[nPos].pSucc = _pBlock + nPos +1; + } + } +} +//__________________________________________________________________________________________________ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +inline LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::~LRU_Cache() +{ + delete [] _pBlock; +} +//__________________________________________________________________________________________________ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +inline void LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::toFront( CacheEntry * pEntry ) const +{ + if (pEntry != _pHead) + { + // cut out element + if (pEntry == _pTail) + { + _pTail = pEntry->pPred; + } + else + { + pEntry->pSucc->pPred = pEntry->pPred; + pEntry->pPred->pSucc = pEntry->pSucc; + } + // push to front + _pHead->pPred = pEntry; + pEntry->pSucc = _pHead; + _pHead = pEntry; + } +} +//__________________________________________________________________________________________________ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +inline sal_Bool LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::hasValue( const t_Key & rKey ) const +{ + ::osl::MutexGuard aGuard( _aCacheMutex ); + const typename t_Key2Element::const_iterator iFind( _aKey2Element.find( rKey ) ); + return (iFind != _aKey2Element.end()); +} +//__________________________________________________________________________________________________ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +inline t_Val LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::getValue( const t_Key & rKey ) const +{ + ::osl::MutexGuard aGuard( _aCacheMutex ); + const typename t_Key2Element::const_iterator iFind( _aKey2Element.find( rKey ) ); + if (iFind != _aKey2Element.end()) + { + CacheEntry * pEntry = (*iFind).second; + toFront( pEntry ); +#ifdef __CACHE_DIAGNOSE + OSL_TRACE( "> retrieved element \"" ); + OSL_TRACE( ::rtl::OUStringToOString( pEntry->aKey, RTL_TEXTENCODING_ASCII_US ).getStr() ); + OSL_TRACE( "\" from cache <\n" ); +#endif + return pEntry->aVal; + } + return t_Val(); +} +//__________________________________________________________________________________________________ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +inline void LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::setValue( + const t_Key & rKey, const t_Val & rValue ) +{ + ::osl::MutexGuard aGuard( _aCacheMutex ); + if (_nCachedElements > 0) + { + const typename t_Key2Element::const_iterator iFind( _aKey2Element.find( rKey ) ); + + CacheEntry * pEntry; + if (iFind == _aKey2Element.end()) + { + pEntry = _pTail; // erase last element +#ifdef __CACHE_DIAGNOSE + if (pEntry->aKey.getLength()) + { + OSL_TRACE( "> kicking element \"" ); + OSL_TRACE( ::rtl::OUStringToOString( pEntry->aKey, RTL_TEXTENCODING_ASCII_US ).getStr() ); + OSL_TRACE( "\" from cache <\n" ); + } +#endif + _aKey2Element.erase( pEntry->aKey ); + _aKey2Element[ pEntry->aKey = rKey ] = pEntry; + } + else + { + pEntry = (*iFind).second; +#ifdef __CACHE_DIAGNOSE + OSL_TRACE( "> replacing element \"" ); + OSL_TRACE( ::rtl::OUStringToOString( pEntry->aKey, RTL_TEXTENCODING_ASCII_US ).getStr() ); + OSL_TRACE( "\" in cache <\n" ); +#endif + } + pEntry->aVal = rValue; + toFront( pEntry ); + } +} +//__________________________________________________________________________________________________ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +inline void LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::clear() +{ + ::osl::MutexGuard aGuard( _aCacheMutex ); + _aKey2Element.clear(); + for ( sal_Int32 nPos = _nCachedElements; nPos--; ) + { + _pBlock[nPos].aKey = t_Key(); + _pBlock[nPos].aVal = t_Val(); + } + _nCachedElements = 0; +#ifdef __CACHE_DIAGNOSE + OSL_TRACE( "> cleared cache <\n" ); +#endif +} + +//================================================================================================== +struct FctHashOUString : public ::std::unary_function< const ::rtl::OUString &, size_t > +{ + size_t operator()( const ::rtl::OUString & rKey ) const + { return rKey.hashCode(); } +}; + +/** Template instance for OUString keys, Any values.<br> +*/ +typedef LRU_Cache< ::rtl::OUString, ::com::sun::star::uno::Any, + FctHashOUString, ::std::equal_to< ::rtl::OUString > > + LRU_CacheAnyByOUString; + + +#endif diff --git a/stoc/source/corereflection/makefile.mk b/stoc/source/corereflection/makefile.mk new file mode 100644 index 000000000000..7156f6d63cc4 --- /dev/null +++ b/stoc/source/corereflection/makefile.mk @@ -0,0 +1,82 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME= stoc +TARGET = reflection.uno +ENABLE_EXCEPTIONS=TRUE +COMP1TYPELIST = corefl + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +DLLPRE = + +# ------------------------------------------------------------------ + +.INCLUDE : ..$/cppumaker.mk + +SLOFILES= \ + $(SLO)$/crefl.obj \ + $(SLO)$/crbase.obj \ + $(SLO)$/crarray.obj \ + $(SLO)$/crcomp.obj \ + $(SLO)$/criface.obj \ + $(SLO)$/crenum.obj + +# internal compiler error with Forte 6 update 1 (x86) +# to be reconsidered after compiler upgrade +.IF "$(OS)$(CPU)"=="SOLARISI" +NOOPTFILES += $(SLO)$/criface.obj +.ENDIF + +SHL1TARGET= $(TARGET) +SHL1VERSIONMAP = $(SOLARENV)/src/unloadablecomponent.map +SHL1STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) + +SHL1DEPN= +SHL1IMPLIB= i$(TARGET) +SHL1LIBS= $(SLB)$/$(TARGET).lib +SHL1DEF= $(MISC)$/$(SHL1TARGET).def +SHL1RPATH= URELIB + +DEF1NAME= $(SHL1TARGET) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +ALLTAR : $(MISC)/reflection.component + +$(MISC)/reflection.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + reflection.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_URE_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt reflection.component diff --git a/stoc/source/corereflection/reflection.component b/stoc/source/corereflection/reflection.component new file mode 100644 index 000000000000..00772a448367 --- /dev/null +++ b/stoc/source/corereflection/reflection.component @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.stoc.CoreReflection"> + <service name="com.sun.star.reflection.CoreReflection"/> + <singleton name="com.sun.star.reflection.theCoreReflection"/> + </implementation> +</component> diff --git a/stoc/source/cppumaker.mk b/stoc/source/cppumaker.mk new file mode 100644 index 000000000000..899c43292834 --- /dev/null +++ b/stoc/source/cppumaker.mk @@ -0,0 +1,41 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +.IF "$(BOOTSTRAP_SERVICE)" != "" +# fully functional C++-UNO (no bridging); no types.rdb needed at runtime +CPPUMAKERFLAGS = +.ENDIF + +.IF "$(debug)" != "" + +# MSVC++: no inlining +.IF "$(COM)" == "MSC" +CFLAGS += -Ob0 +.ENDIF + +.ENDIF + diff --git a/stoc/source/defaultregistry/defaultregistry.cxx b/stoc/source/defaultregistry/defaultregistry.cxx new file mode 100644 index 000000000000..b56e47698c02 --- /dev/null +++ b/stoc/source/defaultregistry/defaultregistry.cxx @@ -0,0 +1,1423 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include <osl/mutex.hxx> +#ifndef _OSL_DIAGNOSE_HXX_ +#include <osl/diagnose.h> +#endif +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/weak.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase4.hxx> +#include <cppuhelper/implbase3.hxx> +#ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_ +#include <cppuhelper/implementationentry.hxx> +#endif +#include <registry/registry.hxx> + +#include <com/sun/star/registry/XSimpleRegistry.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> + +#include <bootstrapservices.hxx> + +using namespace com::sun::star::uno; +using namespace com::sun::star::registry; +using namespace com::sun::star::lang; +using namespace com::sun::star::container; +using namespace cppu; +using namespace osl; +using namespace rtl; + + +#define SERVICENAME "com.sun.star.registry.NestedRegistry" +#define IMPLNAME "com.sun.star.comp.stoc.NestedRegistry" + +extern rtl_StandardModuleCount g_moduleCount; + +namespace stoc_bootstrap +{ +Sequence< OUString > defreg_getSupportedServiceNames() +{ + static Sequence < OUString > *pNames = 0; + if( ! pNames ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( !pNames ) + { + static Sequence< OUString > seqNames(1); + seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME)); + pNames = &seqNames; + } + } + return *pNames; +} + +OUString defreg_getImplementationName() +{ + static OUString *pImplName = 0; + if( ! pImplName ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( ! pImplName ) + { + static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) ); + pImplName = &implName; + } + } + return *pImplName; +} +} + +namespace stoc_defreg +{ +//************************************************************************* +// NestedRegistryImpl +//************************************************************************* +class NestedKeyImpl; + +class NestedRegistryImpl : public WeakAggImplHelper4 < XSimpleRegistry, XInitialization, XServiceInfo, XEnumerationAccess > +{ +public: + NestedRegistryImpl( ); + + ~NestedRegistryImpl(); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) throw(RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw(RuntimeException); + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) throw(RuntimeException); + + // XInitialization + virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) + throw(Exception, RuntimeException); + + // XSimpleRegistry + virtual OUString SAL_CALL getURL() throw(RuntimeException); + virtual void SAL_CALL open( const OUString& rURL, sal_Bool bReadOnly, sal_Bool bCreate ) throw(InvalidRegistryException, RuntimeException); + virtual sal_Bool SAL_CALL isValid( ) throw(RuntimeException); + virtual void SAL_CALL close( ) throw(InvalidRegistryException, RuntimeException); + virtual void SAL_CALL destroy( ) throw(InvalidRegistryException, RuntimeException); + virtual Reference< XRegistryKey > SAL_CALL getRootKey( ) throw(InvalidRegistryException, RuntimeException); + virtual sal_Bool SAL_CALL isReadOnly( ) throw(InvalidRegistryException, RuntimeException); + virtual void SAL_CALL mergeKey( const OUString& aKeyName, const OUString& aUrl ) throw(InvalidRegistryException, MergeConflictException, RuntimeException); + + // XEnumerationAccess + virtual Reference< XEnumeration > SAL_CALL createEnumeration( ) throw (RuntimeException); + virtual Type SAL_CALL getElementType( ) throw (RuntimeException); + virtual sal_Bool SAL_CALL hasElements( ) throw (RuntimeException); + + friend class NestedKeyImpl; +protected: + Mutex m_mutex; + sal_uInt32 m_state; + Reference<XSimpleRegistry> m_localReg; + Reference<XSimpleRegistry> m_defaultReg; + +}; + +//************************************************************************* +// class NestedKeyImpl the implenetation of interface XRegistryKey +//************************************************************************* +class NestedKeyImpl : public WeakImplHelper1< XRegistryKey > +{ +public: + NestedKeyImpl( NestedRegistryImpl* pDefaultRegistry, + Reference<XRegistryKey>& localKey, + Reference<XRegistryKey>& defaultKey); + + NestedKeyImpl( const OUString& aKeyName, + NestedKeyImpl* pKey); + + ~NestedKeyImpl(); + + // XRegistryKey + virtual OUString SAL_CALL getKeyName() throw(RuntimeException); + virtual sal_Bool SAL_CALL isReadOnly( ) throw(InvalidRegistryException, RuntimeException); + virtual sal_Bool SAL_CALL isValid( ) throw(RuntimeException); + virtual RegistryKeyType SAL_CALL getKeyType( const OUString& rKeyName ) throw(InvalidRegistryException, RuntimeException); + virtual RegistryValueType SAL_CALL getValueType( ) throw(InvalidRegistryException, RuntimeException); + virtual sal_Int32 SAL_CALL getLongValue( ) throw(InvalidRegistryException, InvalidValueException, RuntimeException); + virtual void SAL_CALL setLongValue( sal_Int32 value ) throw(InvalidRegistryException, RuntimeException); + virtual Sequence< sal_Int32 > SAL_CALL getLongListValue( ) throw(InvalidRegistryException, InvalidValueException, RuntimeException); + virtual void SAL_CALL setLongListValue( const ::com::sun::star::uno::Sequence< sal_Int32 >& seqValue ) throw(InvalidRegistryException, RuntimeException); + virtual OUString SAL_CALL getAsciiValue( ) throw(InvalidRegistryException, InvalidValueException, RuntimeException); + virtual void SAL_CALL setAsciiValue( const OUString& value ) throw(InvalidRegistryException, RuntimeException); + virtual Sequence< OUString > SAL_CALL getAsciiListValue( ) throw(InvalidRegistryException, InvalidValueException, RuntimeException); + virtual void SAL_CALL setAsciiListValue( const ::com::sun::star::uno::Sequence< OUString >& seqValue ) throw(InvalidRegistryException, RuntimeException); + virtual OUString SAL_CALL getStringValue( ) throw(InvalidRegistryException, InvalidValueException, RuntimeException); + virtual void SAL_CALL setStringValue( const OUString& value ) throw(InvalidRegistryException, RuntimeException); + virtual Sequence< OUString > SAL_CALL getStringListValue( ) throw(InvalidRegistryException, InvalidValueException, RuntimeException); + virtual void SAL_CALL setStringListValue( const ::com::sun::star::uno::Sequence< OUString >& seqValue ) throw(InvalidRegistryException, RuntimeException); + virtual Sequence< sal_Int8 > SAL_CALL getBinaryValue( ) throw(InvalidRegistryException, InvalidValueException, RuntimeException); + virtual void SAL_CALL setBinaryValue( const ::com::sun::star::uno::Sequence< sal_Int8 >& value ) throw(InvalidRegistryException, RuntimeException); + virtual Reference< XRegistryKey > SAL_CALL openKey( const OUString& aKeyName ) throw(InvalidRegistryException, RuntimeException); + virtual Reference< XRegistryKey > SAL_CALL createKey( const OUString& aKeyName ) throw(InvalidRegistryException, RuntimeException); + virtual void SAL_CALL closeKey( ) throw(InvalidRegistryException, RuntimeException); + virtual void SAL_CALL deleteKey( const OUString& rKeyName ) throw(InvalidRegistryException, RuntimeException); + virtual Sequence< Reference< XRegistryKey > > SAL_CALL openKeys( ) throw(InvalidRegistryException, RuntimeException); + virtual Sequence< OUString > SAL_CALL getKeyNames( ) throw(InvalidRegistryException, RuntimeException); + virtual sal_Bool SAL_CALL createLink( const OUString& aLinkName, const OUString& aLinkTarget ) throw(InvalidRegistryException, RuntimeException); + virtual void SAL_CALL deleteLink( const OUString& rLinkName ) throw(InvalidRegistryException, RuntimeException); + virtual OUString SAL_CALL getLinkTarget( const OUString& rLinkName ) throw(InvalidRegistryException, RuntimeException); + virtual OUString SAL_CALL getResolvedName( const OUString& aKeyName ) throw(InvalidRegistryException, RuntimeException); + +protected: + void computeChanges(); + OUString computeName(const OUString& name); + + OUString m_name; + sal_uInt32 m_state; + NestedRegistryImpl* m_pRegistry; + Reference<XRegistryKey> m_localKey; + Reference<XRegistryKey> m_defaultKey; +}; + + +//************************************************************************* +NestedKeyImpl::NestedKeyImpl( NestedRegistryImpl* pDefaultRegistry, + Reference<XRegistryKey>& localKey, + Reference<XRegistryKey>& defaultKey ) + : m_pRegistry(pDefaultRegistry) +{ + m_pRegistry->acquire(); + + m_localKey = localKey; + m_defaultKey = defaultKey; + + if (m_localKey.is()) + { + m_name = m_localKey->getKeyName(); + } else + if (m_defaultKey.is()) + { + m_name = m_defaultKey->getKeyName(); + } + + m_state = m_pRegistry->m_state; +} + +//************************************************************************* +NestedKeyImpl::NestedKeyImpl( const OUString& rKeyName, + NestedKeyImpl* pKey) + : m_pRegistry(pKey->m_pRegistry) +{ + m_pRegistry->acquire(); + + if (pKey->m_localKey.is() && pKey->m_localKey->isValid()) + { + m_localKey = pKey->m_localKey->openKey(rKeyName); + } + if (pKey->m_defaultKey.is() && pKey->m_defaultKey->isValid()) + { + m_defaultKey = pKey->m_defaultKey->openKey(rKeyName); + } + + if (m_localKey.is()) + { + m_name = m_localKey->getKeyName(); + } else + if (m_defaultKey.is()) + { + m_name = m_defaultKey->getKeyName(); + } + + m_state = m_pRegistry->m_state; +} + +//************************************************************************* +NestedKeyImpl::~NestedKeyImpl() +{ + if ( m_pRegistry ) + m_pRegistry->release(); +} + +//************************************************************************* +void NestedKeyImpl::computeChanges() +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( m_state != m_pRegistry->m_state ) + { + Reference<XRegistryKey> rootKey(m_pRegistry->m_localReg->getRootKey()); + + Reference<XRegistryKey> tmpKey = rootKey->openKey(m_name); + + if ( tmpKey.is() ) + { + m_localKey = rootKey->openKey(m_name); + } + + m_state = m_pRegistry->m_state; + } +} + +//************************************************************************* +// NestedKey_Impl::computeName() +// +OUString NestedKeyImpl::computeName(const OUString& name) +{ + OUString resLocalName, resDefaultName; + + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + try + { + if ( m_localKey.is() && m_localKey->isValid() ) + { + resLocalName = m_localKey->getResolvedName(name); + } else + { + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + return m_defaultKey->getResolvedName(name); + } + + if ( resLocalName.getLength() > 0 && m_pRegistry->m_defaultReg->isValid() ) + { + Reference<XRegistryKey> localRoot(m_pRegistry->m_localReg->getRootKey()); + Reference<XRegistryKey> defaultRoot(m_pRegistry->m_defaultReg->getRootKey()); + + resDefaultName = defaultRoot->getResolvedName(resLocalName); + + sal_uInt32 count = 100; + + while (resLocalName != resDefaultName && count > 0) + { + count--; + + if (resLocalName.getLength() == 0 || resDefaultName.getLength() == 0) + throw InvalidRegistryException(); + + resLocalName = localRoot->getResolvedName(resDefaultName); + resDefaultName = defaultRoot->getResolvedName(resLocalName); + } + } + } + catch(InvalidRegistryException& ) + { + } + + return resLocalName; +} + +//************************************************************************* +OUString SAL_CALL NestedKeyImpl::getKeyName() throw(RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + return m_name; +} + +//************************************************************************* +sal_Bool SAL_CALL NestedKeyImpl::isReadOnly( ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + computeChanges(); + + if ( m_localKey.is() && m_localKey->isValid() ) + return m_localKey->isReadOnly(); + else + throw InvalidRegistryException(); +} + +//************************************************************************* +sal_Bool SAL_CALL NestedKeyImpl::isValid( ) throw(RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + return ((m_localKey.is() && m_localKey->isValid()) || + (m_defaultKey.is() && m_defaultKey->isValid()) ); +} + +//************************************************************************* +RegistryKeyType SAL_CALL NestedKeyImpl::getKeyType( const OUString& rKeyName ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + computeChanges(); + + if ( m_localKey.is() && m_localKey->isValid() ) + { + return m_localKey->getKeyType(rKeyName); + } else + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + return m_defaultKey->getKeyType(rKeyName); + } + + return RegistryKeyType_KEY; +} + +//************************************************************************* +RegistryValueType SAL_CALL NestedKeyImpl::getValueType( ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + computeChanges(); + + if ( m_localKey.is() && m_localKey->isValid() ) + { + return m_localKey->getValueType(); + } else + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + return m_defaultKey->getValueType(); + } + + return RegistryValueType_NOT_DEFINED; +} + +//************************************************************************* +sal_Int32 SAL_CALL NestedKeyImpl::getLongValue( ) + throw(InvalidRegistryException, InvalidValueException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + computeChanges(); + + if ( m_localKey.is() && m_localKey->isValid() ) + { + return m_localKey->getLongValue(); + } else + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + return m_defaultKey->getLongValue(); + } else + { + throw InvalidRegistryException(); + } +} + +//************************************************************************* +void SAL_CALL NestedKeyImpl::setLongValue( sal_Int32 value ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + computeChanges(); + + if ( m_localKey.is() && m_localKey->isValid() ) + { + m_localKey->setLongValue(value); + } else + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + Reference<XRegistryKey> rootKey(m_pRegistry->m_localReg->getRootKey()); + m_localKey = rootKey->createKey(m_name); + m_localKey->setLongValue(value); + m_state = m_pRegistry->m_state++; + } else + { + throw InvalidRegistryException(); + } +} + +//************************************************************************* +Sequence< sal_Int32 > SAL_CALL NestedKeyImpl::getLongListValue( ) + throw(InvalidRegistryException, InvalidValueException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + computeChanges(); + + if ( m_localKey.is() && m_localKey->isValid() ) + { + return m_localKey->getLongListValue(); + } else + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + return m_defaultKey->getLongListValue(); + } else + { + throw InvalidRegistryException(); + } +} + +//************************************************************************* +void SAL_CALL NestedKeyImpl::setLongListValue( const Sequence< sal_Int32 >& seqValue ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + computeChanges(); + + if ( m_localKey.is() && m_localKey->isValid() ) + { + m_localKey->setLongListValue(seqValue); + } else + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + Reference<XRegistryKey> rootKey(m_pRegistry->m_localReg->getRootKey()); + m_localKey = rootKey->createKey(m_name); + m_localKey->setLongListValue(seqValue); + m_state = m_pRegistry->m_state++; + } else + { + throw InvalidRegistryException(); + } +} + +//************************************************************************* +OUString SAL_CALL NestedKeyImpl::getAsciiValue( ) + throw(InvalidRegistryException, InvalidValueException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + computeChanges(); + + if ( m_localKey.is() && m_localKey->isValid() ) + { + return m_localKey->getAsciiValue(); + } else + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + return m_defaultKey->getAsciiValue(); + } else + { + throw InvalidRegistryException(); + } +} + +//************************************************************************* +void SAL_CALL NestedKeyImpl::setAsciiValue( const OUString& value ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + computeChanges(); + + if ( m_localKey.is() && m_localKey->isValid() ) + { + m_localKey->setAsciiValue(value); + } else + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + Reference<XRegistryKey> rootKey(m_pRegistry->m_localReg->getRootKey()); + m_localKey = rootKey->createKey(m_name); + m_localKey->setAsciiValue(value); + m_state = m_pRegistry->m_state++; + } else + { + throw InvalidRegistryException(); + } +} + +//************************************************************************* +Sequence< OUString > SAL_CALL NestedKeyImpl::getAsciiListValue( ) + throw(InvalidRegistryException, InvalidValueException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + computeChanges(); + + if ( m_localKey.is() && m_localKey->isValid() ) + { + return m_localKey->getAsciiListValue(); + } else + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + return m_defaultKey->getAsciiListValue(); + } else + { + throw InvalidRegistryException(); + } +} + +//************************************************************************* +void SAL_CALL NestedKeyImpl::setAsciiListValue( const Sequence< OUString >& seqValue ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + computeChanges(); + + if ( m_localKey.is() && m_localKey->isValid() ) + { + m_localKey->setAsciiListValue(seqValue); + } else + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + Reference<XRegistryKey> rootKey(m_pRegistry->m_localReg->getRootKey()); + m_localKey = rootKey->createKey(m_name); + m_localKey->setAsciiListValue(seqValue); + m_state = m_pRegistry->m_state++; + } else + { + throw InvalidRegistryException(); + } +} + +//************************************************************************* +OUString SAL_CALL NestedKeyImpl::getStringValue( ) + throw(InvalidRegistryException, InvalidValueException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + computeChanges(); + + if ( m_localKey.is() && m_localKey->isValid() ) + { + return m_localKey->getStringValue(); + } else + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + return m_defaultKey->getStringValue(); + } else + { + throw InvalidRegistryException(); + } +} + +//************************************************************************* +void SAL_CALL NestedKeyImpl::setStringValue( const OUString& value ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + computeChanges(); + + if ( m_localKey.is() && m_localKey->isValid() ) + { + m_localKey->setStringValue(value); + } else + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + Reference<XRegistryKey> rootKey(m_pRegistry->m_localReg->getRootKey()); + m_localKey = rootKey->createKey(m_name); + m_localKey->setStringValue(value); + m_state = m_pRegistry->m_state++; + } else + { + throw InvalidRegistryException(); + } +} + +//************************************************************************* +Sequence< OUString > SAL_CALL NestedKeyImpl::getStringListValue( ) + throw(InvalidRegistryException, InvalidValueException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + computeChanges(); + + if ( m_localKey.is() && m_localKey->isValid() ) + { + return m_localKey->getStringListValue(); + } else + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + return m_defaultKey->getStringListValue(); + } else + { + throw InvalidRegistryException(); + } +} + +//************************************************************************* +void SAL_CALL NestedKeyImpl::setStringListValue( const Sequence< OUString >& seqValue ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + computeChanges(); + + if ( m_localKey.is() && m_localKey->isValid() ) + { + m_localKey->setStringListValue(seqValue); + } else + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + Reference<XRegistryKey> rootKey(m_pRegistry->m_localReg->getRootKey()); + m_localKey = rootKey->createKey(m_name); + m_localKey->setStringListValue(seqValue); + m_state = m_pRegistry->m_state++; + } else + { + throw InvalidRegistryException(); + } +} + +//************************************************************************* +Sequence< sal_Int8 > SAL_CALL NestedKeyImpl::getBinaryValue( ) + throw(InvalidRegistryException, InvalidValueException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + computeChanges(); + + if ( m_localKey.is() && m_localKey->isValid() ) + { + return m_localKey->getBinaryValue(); + } else + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + return m_defaultKey->getBinaryValue(); + } else + { + throw InvalidRegistryException(); + } +} + +//************************************************************************* +void SAL_CALL NestedKeyImpl::setBinaryValue( const Sequence< sal_Int8 >& value ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + computeChanges(); + + if ( m_localKey.is() && m_localKey->isValid() ) + { + m_localKey->setBinaryValue(value); + } else + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + Reference<XRegistryKey> rootKey(m_pRegistry->m_localReg->getRootKey()); + m_localKey = rootKey->createKey(m_name); + m_localKey->setBinaryValue(value); + m_state = m_pRegistry->m_state++; + } else + { + throw InvalidRegistryException(); + } +} + +//************************************************************************* +Reference< XRegistryKey > SAL_CALL NestedKeyImpl::openKey( const OUString& aKeyName ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_localKey.is() && !m_defaultKey.is() ) + { + throw InvalidRegistryException(); + } + + OUString resolvedName = computeName(aKeyName); + + if ( resolvedName.getLength() == 0 ) + throw InvalidRegistryException(); + + Reference<XRegistryKey> localKey, defaultKey; + + if ( m_localKey.is() && m_localKey->isValid() ) + { + localKey = m_pRegistry->m_localReg->getRootKey()->openKey(resolvedName); + } + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + defaultKey = m_pRegistry->m_defaultReg->getRootKey()->openKey(resolvedName); + } + + if ( localKey.is() || defaultKey.is() ) + { + return ((XRegistryKey*)new NestedKeyImpl(m_pRegistry, localKey, defaultKey)); + } else + { + return Reference<XRegistryKey>(); + } +} + +//************************************************************************* +Reference< XRegistryKey > SAL_CALL NestedKeyImpl::createKey( const OUString& aKeyName ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( (!m_localKey.is() && !m_defaultKey.is()) || + (m_localKey.is() && m_localKey->isReadOnly()) ) + { + throw InvalidRegistryException(); + } + + OUString resolvedName = computeName(aKeyName); + + if ( resolvedName.getLength() == 0 ) + throw InvalidRegistryException(); + + if ( m_localKey.is() && m_localKey->isValid() ) + { + Reference<XRegistryKey> localKey, defaultKey; + + localKey = m_pRegistry->m_localReg->getRootKey()->createKey(resolvedName); + if ( localKey.is() ) + { + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + defaultKey = m_pRegistry->m_defaultReg->getRootKey()->openKey(resolvedName); + } + + m_state = m_pRegistry->m_state++; + + return ((XRegistryKey*)new NestedKeyImpl(m_pRegistry, localKey, defaultKey)); + } + } else + { + Reference<XRegistryKey> localKey, defaultKey; + + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + Reference<XRegistryKey> rootKey(m_pRegistry->m_localReg->getRootKey()); + m_localKey = rootKey->createKey(m_name); + + localKey = m_pRegistry->m_localReg->getRootKey()->createKey(resolvedName); + + if ( localKey.is() ) + { + defaultKey = m_pRegistry->m_defaultReg->getRootKey()->openKey(resolvedName); + + m_state = m_pRegistry->m_state++; + + return ((XRegistryKey*)new NestedKeyImpl(m_pRegistry, localKey, defaultKey)); + } + } + } + + return Reference<XRegistryKey>(); +} + +//************************************************************************* +void SAL_CALL NestedKeyImpl::closeKey( ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( m_localKey.is() && m_localKey->isValid() ) + { + m_localKey->closeKey(); + } + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + m_defaultKey->closeKey(); + } +} + +//************************************************************************* +void SAL_CALL NestedKeyImpl::deleteKey( const OUString& rKeyName ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( m_localKey.is() && m_localKey->isValid() && + !m_localKey->isReadOnly() ) + { + OUString resolvedName = computeName(rKeyName); + + if ( resolvedName.getLength() == 0 ) + { + throw InvalidRegistryException(); + } + + m_pRegistry->m_localReg->getRootKey()->deleteKey(resolvedName); + } else + { + throw InvalidRegistryException(); + } +} + +//************************************************************************* +Sequence< Reference< XRegistryKey > > SAL_CALL NestedKeyImpl::openKeys( ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_localKey.is() && !m_defaultKey.is() ) + { + throw InvalidRegistryException(); + } + + Sequence<OUString> localSeq, defaultSeq; + + if ( m_localKey.is() && m_localKey->isValid() ) + { + localSeq = m_localKey->getKeyNames(); + } + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + defaultSeq = m_defaultKey->getKeyNames(); + } + + sal_uInt32 local = localSeq.getLength(); + sal_uInt32 def = defaultSeq.getLength(); + sal_uInt32 len = 0; + + sal_uInt32 i, j; + for (i=0; i < local; i++) + { + for (j=0 ; j < def; j++) + { + if ( localSeq.getConstArray()[i] == defaultSeq.getConstArray()[j] ) + { + len++; + break; + } + } + } + + Sequence< Reference<XRegistryKey> > retSeq(local + def - len); + sal_Bool insert = sal_True; + OUString name; + sal_Int32 lastIndex; + + for (i=0; i < local; i++) + { + name = localSeq.getConstArray()[i]; + lastIndex = name.lastIndexOf('/'); + name = name.copy(lastIndex); + retSeq.getArray()[i] = + (XRegistryKey*)new NestedKeyImpl(name, this); + } + + sal_uInt32 k = local; + for (i=0; i < def; i++) + { + insert = sal_True; + + for (j=0 ; j < local; j++) + { + if ( retSeq.getConstArray()[j]->getKeyName() + == defaultSeq.getConstArray()[i] ) + { + insert = sal_False; + break; + } + } + + if ( insert ) + { + name = defaultSeq.getConstArray()[i]; + lastIndex = name.lastIndexOf('/'); + name = name.copy(lastIndex); + retSeq.getArray()[k++] = + (XRegistryKey*)new NestedKeyImpl(name, this); + } + } + + return retSeq; +} + +//************************************************************************* +Sequence< OUString > SAL_CALL NestedKeyImpl::getKeyNames( ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_localKey.is() && !m_defaultKey.is() ) + { + throw InvalidRegistryException(); + } + + Sequence<OUString> localSeq, defaultSeq; + + if ( m_localKey.is() && m_localKey->isValid() ) + { + localSeq = m_localKey->getKeyNames(); + } + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + defaultSeq = m_defaultKey->getKeyNames(); + } + + sal_uInt32 local = localSeq.getLength(); + sal_uInt32 def = defaultSeq.getLength(); + sal_uInt32 len = 0; + + sal_uInt32 i, j; + for (i=0; i < local; i++) + { + for (j=0 ; j < def; j++) + { + if ( localSeq.getConstArray()[i] == defaultSeq.getConstArray()[j] ) + { + len++; + break; + } + } + } + + Sequence<OUString> retSeq(local + def - len); + sal_Bool insert = sal_True; + + for (i=0; i < local; i++) + { + retSeq.getArray()[i] = localSeq.getConstArray()[i]; + } + + sal_uInt32 k = local; + for (i=0; i < def; i++) + { + insert = sal_True; + + for (j=0 ; j < local; j++) + { + if ( retSeq.getConstArray()[j] == defaultSeq.getConstArray()[i] ) + { + insert = sal_False; + break; + } + } + + if ( insert ) + retSeq.getArray()[k++] = defaultSeq.getConstArray()[i]; + } + + return retSeq; +} + +//************************************************************************* +sal_Bool SAL_CALL NestedKeyImpl::createLink( const OUString& aLinkName, const OUString& aLinkTarget ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + + sal_Bool isCreated = sal_False; + if ( !m_localKey.is() && !m_defaultKey.is() ) + { + throw InvalidRegistryException(); + } + + OUString linkName; + OUString resolvedName; + sal_Int32 lastIndex = aLinkName.lastIndexOf('/'); + + if ( lastIndex > 0 ) + { + linkName = aLinkName.copy(0, lastIndex); + + resolvedName = computeName(linkName); + + if ( resolvedName.getLength() == 0 ) + { + throw InvalidRegistryException(); + } + + resolvedName = resolvedName + aLinkName.copy(lastIndex); + } else + { + if ( lastIndex == 0 ) + resolvedName = m_name + aLinkName; + else + resolvedName = m_name + OUString( RTL_CONSTASCII_USTRINGPARAM("/") ) + aLinkName; + } + + if ( m_localKey.is() && m_localKey->isValid() ) + { + isCreated = m_pRegistry->m_localReg->getRootKey()->createLink(resolvedName, aLinkTarget); + } else + { + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + { + Reference<XRegistryKey> rootKey(m_pRegistry->m_localReg->getRootKey()); + m_localKey = rootKey->createKey(m_name); + + isCreated = m_pRegistry->m_localReg->getRootKey()->createLink(resolvedName, aLinkTarget); + } + } + + if ( isCreated ) + m_state = m_pRegistry->m_state++; + + return isCreated; +} + +//************************************************************************* +void SAL_CALL NestedKeyImpl::deleteLink( const OUString& rLinkName ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_localKey.is() && !m_defaultKey.is() ) + { + throw InvalidRegistryException(); + } + + OUString linkName; + OUString resolvedName; + sal_Int32 lastIndex = rLinkName.lastIndexOf('/'); + + if ( lastIndex > 0 ) + { + linkName = rLinkName.copy(0, lastIndex); + + resolvedName = computeName(linkName); + + if ( resolvedName.getLength() == 0 ) + { + throw InvalidRegistryException(); + } + + resolvedName = resolvedName + rLinkName.copy(lastIndex); + } else + { + if ( lastIndex == 0 ) + resolvedName = m_name + rLinkName; + else + resolvedName = m_name + OUString( RTL_CONSTASCII_USTRINGPARAM("/") ) + rLinkName; + } + + if ( m_localKey.is() && m_localKey->isValid() && + !m_localKey->isReadOnly() ) + { + m_pRegistry->m_localReg->getRootKey()->deleteLink(resolvedName); + } else + { + throw InvalidRegistryException(); + } +} + +//************************************************************************* +OUString SAL_CALL NestedKeyImpl::getLinkTarget( const OUString& rLinkName ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_localKey.is() && !m_defaultKey.is() ) + { + throw InvalidRegistryException(); + } + + OUString linkName; + OUString resolvedName; + sal_Int32 lastIndex = rLinkName.lastIndexOf('/'); + + if ( lastIndex > 0 ) + { + linkName = rLinkName.copy(0, lastIndex); + + resolvedName = computeName(linkName); + + if ( resolvedName.getLength() == 0 ) + { + throw InvalidRegistryException(); + } + + resolvedName = resolvedName + rLinkName.copy(lastIndex); + } else + { + if ( lastIndex == 0 ) + resolvedName = m_name + rLinkName; + else + resolvedName = m_name + OUString( RTL_CONSTASCII_USTRINGPARAM("/") ) + rLinkName; + } + + OUString linkTarget; + if ( m_localKey.is() && m_localKey->isValid() ) + { + try + { + linkTarget = m_pRegistry->m_localReg->getRootKey()->getLinkTarget(resolvedName); + return linkTarget; + } + catch(InvalidRegistryException& ) + { + } + } + + if ( m_defaultKey.is() && m_defaultKey->isValid() ) + linkTarget = m_pRegistry->m_defaultReg->getRootKey()->getLinkTarget(resolvedName); + + return linkTarget; +} + +//************************************************************************* +OUString SAL_CALL NestedKeyImpl::getResolvedName( const OUString& aKeyName ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_localKey.is() && !m_defaultKey.is() ) + { + throw InvalidRegistryException(); + } + + OUString resolvedName = computeName(aKeyName); + + if ( resolvedName.getLength() == 0 ) + { + throw InvalidRegistryException(); + } + + return resolvedName; +} + +//************************************************************************* +// +// DefaultRegistry Implementation +// +//************************************************************************* +NestedRegistryImpl::NestedRegistryImpl( ) + : m_state(0) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); +} + +//************************************************************************* +NestedRegistryImpl::~NestedRegistryImpl() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + + +class RegistryEnumueration : public WeakImplHelper1< XEnumeration > +{ +public: + RegistryEnumueration( + const Reference< XSimpleRegistry > &r1, + const Reference< XSimpleRegistry > &r2 ) + : m_xReg1( r1 ) , m_xReg2( r2 ) + {} +public: + virtual sal_Bool SAL_CALL hasMoreElements( ) throw (RuntimeException); + virtual Any SAL_CALL nextElement( ) throw (NoSuchElementException, WrappedTargetException, RuntimeException); + +private: + Reference< XSimpleRegistry > m_xReg1; + Reference< XSimpleRegistry > m_xReg2; +}; + +sal_Bool RegistryEnumueration::hasMoreElements( ) throw (RuntimeException) +{ + return m_xReg1.is() || m_xReg2.is(); +} + +Any RegistryEnumueration::nextElement( ) + throw (NoSuchElementException, WrappedTargetException, RuntimeException) +{ + Any a; + if( m_xReg1.is() ) + { + a <<= m_xReg1; + m_xReg1.clear(); + } + else if( m_xReg2.is() ) + { + a <<= m_xReg2; + m_xReg2.clear(); + } + else + { + throw NoSuchElementException( OUString( RTL_CONSTASCII_USTRINGPARAM( + "NestedRegistry: no nextElement() !" ) ),Reference< XInterface > () ); + } + return a; +} + + +Reference< XEnumeration > NestedRegistryImpl::createEnumeration( ) throw (RuntimeException) +{ + MutexGuard guard( m_mutex ); + return new RegistryEnumueration( m_localReg, m_defaultReg ); +} + +Type NestedRegistryImpl::getElementType( ) throw (RuntimeException) +{ + return getCppuType( &m_localReg ); +} + +sal_Bool SAL_CALL NestedRegistryImpl::hasElements( ) throw (RuntimeException) +{ + MutexGuard guard( m_mutex ); + return m_localReg.is() || m_defaultReg.is(); +} + + + +//************************************************************************* +OUString SAL_CALL NestedRegistryImpl::getImplementationName( ) + throw(RuntimeException) +{ + return stoc_bootstrap::defreg_getImplementationName(); +} + +//************************************************************************* +sal_Bool SAL_CALL NestedRegistryImpl::supportsService( const OUString& ServiceName ) + throw(RuntimeException) +{ + Guard< Mutex > aGuard( m_mutex ); + Sequence< OUString > aSNL = getSupportedServiceNames(); + const OUString * pArray = aSNL.getArray(); + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return sal_True; + return sal_False; +} + +//************************************************************************* +Sequence<OUString> SAL_CALL NestedRegistryImpl::getSupportedServiceNames( ) + throw(RuntimeException) +{ + return stoc_bootstrap::defreg_getSupportedServiceNames(); +} + +//************************************************************************* +void SAL_CALL NestedRegistryImpl::initialize( const Sequence< Any >& aArguments ) + throw( Exception, RuntimeException ) +{ + Guard< Mutex > aGuard( m_mutex ); + if ( (aArguments.getLength() == 2) && + (aArguments[0].getValueType().getTypeClass() == TypeClass_INTERFACE) && + (aArguments[1].getValueType().getTypeClass() == TypeClass_INTERFACE) ) + { + aArguments[0] >>= m_localReg; + aArguments[1] >>= m_defaultReg; + if ( m_localReg == m_defaultReg ) + m_defaultReg = Reference< XSimpleRegistry >(); + } +} + +//************************************************************************* +OUString SAL_CALL NestedRegistryImpl::getURL() throw(RuntimeException) +{ + Guard< Mutex > aGuard( m_mutex ); + try + { + if ( m_localReg.is() && m_localReg->isValid() ) + return m_localReg->getURL(); + } + catch(InvalidRegistryException& ) + { + } + + return OUString(); +} + +//************************************************************************* +void SAL_CALL NestedRegistryImpl::open( const OUString&, sal_Bool, sal_Bool ) + throw(InvalidRegistryException, RuntimeException) +{ + throw InvalidRegistryException( + OUString::createFromAscii("the 'open' method is not specified for a nested registry"), + Reference< XInterface >() ); +} + +//************************************************************************* +sal_Bool SAL_CALL NestedRegistryImpl::isValid( ) throw(RuntimeException) +{ + Guard< Mutex > aGuard( m_mutex ); + try + { + if ( (m_localReg.is() && m_localReg->isValid()) || + (m_defaultReg.is() && m_defaultReg->isValid()) ) + return sal_True; + } + catch(InvalidRegistryException& ) + { + } + + return sal_False; +} + +//************************************************************************* +void SAL_CALL NestedRegistryImpl::close( ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_mutex ); + if ( m_localReg.is() && m_localReg->isValid() ) + { + m_localReg->close(); + } + if ( m_defaultReg.is() && m_defaultReg->isValid() ) + { + m_defaultReg->close(); + } +/* + throw InvalidRegistryException( + OUString::createFromAscii("the 'close' method is not specified for a nested registry"), + Reference< XInterface >() ); +*/ +} + +//************************************************************************* +void SAL_CALL NestedRegistryImpl::destroy( ) + throw(InvalidRegistryException, RuntimeException) +{ + throw InvalidRegistryException( + OUString::createFromAscii("the 'destroy' method is not specified for a nested registry"), + Reference< XInterface >() ); +} + +//************************************************************************* +Reference< XRegistryKey > SAL_CALL NestedRegistryImpl::getRootKey( ) + throw(InvalidRegistryException, RuntimeException) +{ + Reference<XRegistryKey> tmpKey; + + Guard< Mutex > aGuard( m_mutex ); + if ( m_localReg.is() && m_localReg->isValid() ) + { + Reference<XRegistryKey> localKey, defaultKey; + + localKey = m_localReg->getRootKey(); + + if ( localKey.is() ) + { + if ( m_defaultReg.is() && m_defaultReg->isValid() ) + { + defaultKey = m_defaultReg->getRootKey(); + } + + return ((XRegistryKey*)new NestedKeyImpl(this, localKey, defaultKey)); + } + } else + { + throw InvalidRegistryException(); + } + + return Reference<XRegistryKey>(); +} + +//************************************************************************* +sal_Bool SAL_CALL NestedRegistryImpl::isReadOnly( ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_mutex ); + try + { + if ( m_localReg.is() && m_localReg->isValid() ) + return m_localReg->isReadOnly(); + } + catch(InvalidRegistryException& ) + { + } + + return sal_False; +} + +//************************************************************************* +void SAL_CALL NestedRegistryImpl::mergeKey( const OUString& aKeyName, const OUString& aUrl ) + throw(InvalidRegistryException, MergeConflictException, RuntimeException) +{ + Guard< Mutex > aGuard( m_mutex ); + if ( m_localReg.is() && m_localReg->isValid() ) + { + m_localReg->mergeKey(aKeyName, aUrl); + + m_state++; + } +} +} // namespace stco_defreg + +namespace stoc_bootstrap +{ +//************************************************************************* +Reference<XInterface> SAL_CALL NestedRegistry_CreateInstance( const Reference<XComponentContext>& ) + throw(Exception) +{ + Reference<XInterface> xRet; + XSimpleRegistry *pRegistry = (XSimpleRegistry*) new stoc_defreg::NestedRegistryImpl; + + if (pRegistry) + { + xRet = Reference<XInterface>::query(pRegistry); + } + + return xRet; +} + +} + diff --git a/stoc/source/defaultregistry/makefile.mk b/stoc/source/defaultregistry/makefile.mk new file mode 100644 index 000000000000..17f25999d169 --- /dev/null +++ b/stoc/source/defaultregistry/makefile.mk @@ -0,0 +1,46 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME= stoc +TARGET = nestedreg +ENABLE_EXCEPTIONS=TRUE +UNOUCROUT= $(OUT)$/inc$/bootstrap +BOOTSTRAP_SERVICE=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# ------------------------------------------------------------------ + +SLOFILES= \ + $(SLO)$/defaultregistry.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/stoc/source/implementationregistration/implreg.cxx b/stoc/source/implementationregistration/implreg.cxx new file mode 100644 index 000000000000..cbb49c162fe1 --- /dev/null +++ b/stoc/source/implementationregistration/implreg.cxx @@ -0,0 +1,1925 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include <stdlib.h> +#include <string.h> +#include <list> + +#include <unistd.h> +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/weak.hxx> +#include <cppuhelper/servicefactory.hxx> +#ifndef _CPPUHELPER_IMPLBASE3_HXX +#include <cppuhelper/implbase3.hxx> +#endif +#ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_ +#include <cppuhelper/implementationentry.hxx> +#endif + +#include <uno/mapping.hxx> +#include <osl/thread.h> + +#include <rtl/ustring.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/strbuf.hxx> +#include <osl/process.h> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/loader/XImplementationLoader.hpp> +#include <com/sun/star/registry/XImplementationRegistration2.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/reflection/XServiceTypeDescription.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include "com/sun/star/uno/RuntimeException.hpp" + +#include "mergekeys.hxx" + +#if defined(SAL_W32) || defined(SAL_OS2) +#include <io.h> +#endif + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + + +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::loader; +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::registry; +using namespace cppu; +using namespace rtl; +using namespace osl; + + +#define IMPLNAME "com.sun.star.comp.stoc.ImplementationRegistration" +#define SERVICENAME "com.sun.star.registry.ImplementationRegistration" +namespace stoc_impreg +{ +struct StringPool +{ + OUString sImplementationName; + OUString sServiceName; + OUString TMP; + OUString TEMP; + OUString slash_UNO_slash_REGISTRY_LINKS; + OUString slash_IMPLEMENTATIONS; + OUString slash_UNO; + OUString slash_UNO_slash_SERVICES; + OUString slash_UNO_slash_SINGLETONS; + OUString slash_SERVICES; + OUString slash_UNO_slash_LOCATION; + OUString slash_UNO_slash_ACTIVATOR; + OUString colon_old; + OUString com_sun_star_registry_SimpleRegistry; + OUString Registry; + StringPool() + : sImplementationName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) ) + , sServiceName( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME ) ) + , TMP( RTL_CONSTASCII_USTRINGPARAM( "TMP" ) ) + , TEMP( RTL_CONSTASCII_USTRINGPARAM( "TEMP" ) ) + , slash_UNO_slash_REGISTRY_LINKS( RTL_CONSTASCII_USTRINGPARAM("/UNO/REGISTRY_LINKS")) + , slash_IMPLEMENTATIONS( RTL_CONSTASCII_USTRINGPARAM( "/IMPLEMENTATIONS" ) ) + , slash_UNO( RTL_CONSTASCII_USTRINGPARAM("/UNO")) + , slash_UNO_slash_SERVICES( RTL_CONSTASCII_USTRINGPARAM("/UNO/SERVICES")) + , slash_UNO_slash_SINGLETONS( RTL_CONSTASCII_USTRINGPARAM("/UNO/SINGLETONS")) + , slash_SERVICES( RTL_CONSTASCII_USTRINGPARAM("/SERVICES/") ) + , slash_UNO_slash_LOCATION( RTL_CONSTASCII_USTRINGPARAM("/UNO/LOCATION") ) + , slash_UNO_slash_ACTIVATOR( RTL_CONSTASCII_USTRINGPARAM("/UNO/ACTIVATOR") ) + , colon_old( RTL_CONSTASCII_USTRINGPARAM(":old")) + , com_sun_star_registry_SimpleRegistry(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.registry.SimpleRegistry") ) + , Registry( RTL_CONSTASCII_USTRINGPARAM("Registry") ) + {} +private: + StringPool( const StringPool & ); +}; + +const StringPool &spool() +{ + static StringPool *pPool = 0; + if( ! pPool ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( ! pPool ) + { + static StringPool pool; + pPool = &pool; + } + } + return *pPool; +} +} + +extern rtl_StandardModuleCount g_moduleCount; + +namespace stoc_bootstrap +{ +Sequence< OUString > impreg_getSupportedServiceNames() +{ + static Sequence < OUString > *pNames = 0; + if( ! pNames ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( !pNames ) + { + static Sequence< OUString > seqNames(1); + seqNames.getArray()[0] = stoc_impreg::spool().sServiceName; + pNames = &seqNames; + } + } + return *pNames; +} + +OUString impreg_getImplementationName() +{ + return stoc_impreg::spool().sImplementationName; +} +} + +namespace stoc_impreg +{ +//************************************************************************* +// static deleteAllLinkReferences() +// +static void deleteAllLinkReferences(const Reference < XSimpleRegistry >& xReg, + const Reference < XRegistryKey >& xSource) + // throw ( InvalidRegistryException, RuntimeException ) +{ + Reference < XRegistryKey > xKey = xSource->openKey( + spool().slash_UNO_slash_REGISTRY_LINKS ); + + if (xKey.is() && (xKey->getValueType() == RegistryValueType_ASCIILIST)) + { + Sequence<OUString> linkNames = xKey->getAsciiListValue(); + + if (linkNames.getLength()) + { + const OUString* pLinkNames = linkNames.getConstArray(); + + OUString aLinkName; + OUString aLinkParent; + Reference < XRegistryKey > xLinkParent; + const sal_Unicode* pTmpName = NULL; + const sal_Unicode* pShortName = NULL; + sal_Int32 sEnd = 0; + + for (sal_Int32 i = 0; i < linkNames.getLength(); i++) + { + aLinkName = pLinkNames[i]; + + pTmpName = aLinkName.getStr(); + + if (pTmpName[0] != L'/') + continue; + + sal_Int32 nIndex = rtl_ustr_indexOfChar( pTmpName, '%' ); + if ( nIndex == -1 ) + pShortName = 0; + else + pShortName = pTmpName+nIndex; + + while (pShortName && pShortName[1] == L'%') + { + nIndex = rtl_ustr_indexOfChar( pShortName+2, '%' ); + if ( nIndex == -1 ) + pShortName = 0; + else + pShortName += nIndex+2; + } + + if (pShortName) + { + aLinkName = aLinkName.copy(0, pShortName - pTmpName); + } + + xReg->getRootKey()->deleteLink(aLinkName); + + sEnd = rtl_ustr_lastIndexOfChar( aLinkName.getStr(), '/' ); + + aLinkParent = aLinkName.copy(0, sEnd); + + while(aLinkParent.getLength()) + { + xLinkParent = xReg->getRootKey()->openKey(aLinkParent); + + if (xLinkParent.is() && (xLinkParent->getKeyNames().getLength() == 0)) + { + aLinkName = aLinkParent; + + xReg->getRootKey()->deleteKey(aLinkParent); + + sEnd = rtl_ustr_lastIndexOfChar( aLinkName.getStr(), '/' ); + + aLinkParent = aLinkName.copy(0, sEnd); + } else + { + break; + } + } + } + } + } +} + +//************************************************************************* +// static prepareLink +// +static void prepareLink( const Reference < XSimpleRegistry > & xDest, + const Reference < XRegistryKey > & xSource, + const OUString& link) + // throw ( InvalidRegistryException, RuntimeException ) +{ + OUString linkRefName = xSource->getKeyName(); + OUString linkName(link); + sal_Bool isRelativ = sal_False; + + const sal_Unicode* pTmpName = link.getStr(); + const sal_Unicode* pShortName; + sal_Int32 nIndex = rtl_ustr_indexOfChar( pTmpName, '%' ); + if ( nIndex == -1 ) + pShortName = 0; + else + pShortName = pTmpName+nIndex; + + if (pTmpName[0] != L'/') + isRelativ = sal_True; + + while (pShortName && pShortName[1] == L'%') + { + nIndex = rtl_ustr_indexOfChar( pShortName+2, '%' ); + if ( nIndex == -1 ) + pShortName = 0; + else + pShortName += nIndex+2; + } + + if (pShortName) + { + linkRefName = linkRefName + link.copy(pShortName - pTmpName + 1); + linkName = link.copy(0, pShortName - pTmpName); + } + + if (isRelativ) + xSource->createLink(linkName, linkRefName); + else + xDest->getRootKey()->createLink(linkName, linkRefName); +} + +//************************************************************************* +// static searchImplForLink +// +static OUString searchImplForLink( + const Reference < XRegistryKey > & xRootKey, + const OUString& linkName, + const OUString& implName ) + // throw ( InvalidRegistryException, RuntimeException ) +{ + const StringPool & pool = spool(); + Reference < XRegistryKey > xKey = xRootKey->openKey( pool.slash_IMPLEMENTATIONS ); + if (xKey.is()) + { + Sequence< Reference < XRegistryKey > > subKeys( xKey->openKeys() ); + const Reference < XRegistryKey > * pSubKeys = subKeys.getConstArray(); + OUString key_name( pool.slash_UNO + linkName ); + + for (sal_Int32 i = 0; i < subKeys.getLength(); i++) + { + try + { + Reference < XRegistryKey > xImplKey( pSubKeys[i] ); + if (xImplKey->getKeyType( key_name ) == RegistryKeyType_LINK) + { + OUString oldImplName = xImplKey->getKeyName().copy(strlen("/IMPLEMENTATIONS/")); + if (implName != oldImplName) + { + return oldImplName; + } + } + } + catch(InvalidRegistryException&) + { + } + } + } + + return OUString(); +} + +//************************************************************************* +// static searchLinkTargetForImpl +// +static OUString searchLinkTargetForImpl(const Reference < XRegistryKey >& xRootKey, + const OUString& linkName, + const OUString& implName) + // throw ( InvalidRegistryException, RuntimeException ) +{ + OUString ret; + +// try +// { + const StringPool & pool = spool(); + Reference < XRegistryKey > xKey = xRootKey->openKey( pool.slash_IMPLEMENTATIONS ); + + if (xKey.is()) + { + Sequence< Reference < XRegistryKey > > subKeys = xKey->openKeys(); + + const Reference < XRegistryKey >* pSubKeys = subKeys.getConstArray(); + Reference < XRegistryKey > xImplKey; + + for (sal_Int32 i = 0; i < subKeys.getLength(); i++) + { + xImplKey = pSubKeys[i]; + + OUString tmpImplName = xImplKey->getKeyName().copy(strlen("/IMPLEMENTATIONS/")); + OUString qualifiedLinkName( pool.slash_UNO ); + qualifiedLinkName += linkName; + if (tmpImplName == implName && + xImplKey->getKeyType( qualifiedLinkName ) == RegistryKeyType_LINK) + { + return xImplKey->getLinkTarget( qualifiedLinkName ); + } + } + } +// } +// catch(InvalidRegistryException&) +// { +// } + + return ret; +} + +//************************************************************************* +// static createUniqueSubEntry +// +static void createUniqueSubEntry(const Reference < XRegistryKey > & xSuperKey, + const OUString& value) + // throw ( InvalidRegistryException, RuntimeException ) +{ + if (xSuperKey.is()) + { +// try +// { + if (xSuperKey->getValueType() == RegistryValueType_ASCIILIST) + { + sal_Int32 length = 0; + sal_Bool bReady = sal_False; + + Sequence<OUString> implEntries = xSuperKey->getAsciiListValue(); + length = implEntries.getLength(); + + for (sal_Int32 i = 0; !bReady && (i < length); i++) + { + bReady = (implEntries.getConstArray()[i] == value); + } + + if (bReady) + { + Sequence<OUString> implEntriesNew(length); + implEntriesNew.getArray()[0] = value; + + for (sal_Int32 i=0, j=1; i < length; i++) + { + if (implEntries.getConstArray()[i] != value) + implEntriesNew.getArray()[j++] = implEntries.getConstArray()[i]; + } + xSuperKey->setAsciiListValue(implEntriesNew); + } else + { + Sequence<OUString> implEntriesNew(length+1); + implEntriesNew.getArray()[0] = value; + + for (sal_Int32 i = 0; i < length; i++) + { + implEntriesNew.getArray()[i+1] = implEntries.getConstArray()[i]; + } + xSuperKey->setAsciiListValue(implEntriesNew); + } + } else + { + Sequence<OUString> implEntriesNew(1); + + implEntriesNew.getArray()[0] = value; + + xSuperKey->setAsciiListValue(implEntriesNew); + } +// } +// catch(InvalidRegistryException&) +// { +// } + } +} + +//************************************************************************* +// static deleteSubEntry +// +static sal_Bool deleteSubEntry(const Reference < XRegistryKey >& xSuperKey, const OUString& value) + // throw ( InvalidRegistryException, RuntimeException ) +{ + if (xSuperKey->getValueType() == RegistryValueType_ASCIILIST) + { + Sequence<OUString> implEntries = xSuperKey->getAsciiListValue(); + sal_Int32 length = implEntries.getLength(); + sal_Int32 equals = 0; + sal_Bool hasNoImplementations = sal_False; + + for (sal_Int32 i = 0; i < length; i++) + { + if (implEntries.getConstArray()[i] == value) + equals++; + } + + if (equals == length) + { + hasNoImplementations = sal_True; + } else + { + Sequence<OUString> implEntriesNew(length - equals); + + sal_Int32 j = 0; + for (sal_Int32 i = 0; i < length; i++) + { + if (implEntries.getConstArray()[i] != value) + { + implEntriesNew.getArray()[j++] = implEntries.getConstArray()[i]; + } + } + xSuperKey->setAsciiListValue(implEntriesNew); + } + + if (hasNoImplementations) + { + return sal_True; + } + } + return sal_False; +} + +//************************************************************************* +// static prepareUserLink +// +static void prepareUserLink(const Reference < XSimpleRegistry >& xDest, + const OUString& linkName, + const OUString& linkTarget, + const OUString& implName) + // throw ( InvalidRegistryException, RuntimeException ) +{ + sal_Bool ret = sal_False; + + Reference < XRegistryKey > xRootKey; + +// try +// { + xRootKey = xDest->getRootKey(); + + if (xRootKey->getKeyType(linkName) == RegistryKeyType_LINK) + { + OUString oldImplName(searchImplForLink(xRootKey, linkName, implName)); + + if (oldImplName.getLength()) + { + createUniqueSubEntry(xDest->getRootKey()->createKey( + linkName + spool().colon_old ), oldImplName); + } + } +// } +// catch (InvalidRegistryException&) +// { +// } + +// try +// { + if (xRootKey->isValid()) + { + ret = xRootKey->createLink(linkName, linkTarget); + } +// } +// catch(InvalidRegistryException&) +// { +// } + +// return ret; +} + +//************************************************************************* +// static deleteUserLink +// +static void deletePathIfPossible(const Reference < XRegistryKey >& xRootKey, + const OUString& path) +{ + try + { + Sequence<OUString> keyNames(xRootKey->openKey(path)->getKeyNames()); + + if (keyNames.getLength() == 0 && + xRootKey->openKey(path)->getValueType() == RegistryValueType_NOT_DEFINED) + { + xRootKey->deleteKey(path); + + OUString tmpPath(path); + OUString newPath = tmpPath.copy(0, tmpPath.lastIndexOf('/')); + + if (newPath.getLength() > 1) + deletePathIfPossible(xRootKey, newPath); + } + } + catch(InvalidRegistryException&) + { + } +} + + +//************************************************************************* +// static deleteUserLink +// +static void deleteUserLink(const Reference < XRegistryKey >& xRootKey, + const OUString& linkName, + const OUString& linkTarget, + const OUString& implName) + // throw ( InvalidRegistryException, RuntimeException ) +{ + sal_Bool bClean = sal_False; + + if (xRootKey->getKeyType(linkName) == RegistryKeyType_LINK) + { + OUString tmpTarget = xRootKey->getLinkTarget(linkName); + + if (tmpTarget == linkTarget) + { + xRootKey->deleteLink(linkName); + } + } + + Reference < XRegistryKey > xOldKey = xRootKey->openKey( + linkName + spool().colon_old ); + if (xOldKey.is()) + { + sal_Bool hasNoImplementations = sal_False; + + if (xOldKey->getValueType() == RegistryValueType_ASCIILIST) + { + Sequence<OUString> implEntries = xOldKey->getAsciiListValue(); + sal_Int32 length = implEntries.getLength(); + sal_Int32 equals = 0; + + for (sal_Int32 i = 0; i < length; i++) + { + if (implEntries.getConstArray()[i] == implName) + equals++; + } + + if (equals == length) + { + hasNoImplementations = sal_True; + } else + { + OUString oldImpl; + + if (length > equals + 1) + { + Sequence<OUString> implEntriesNew(length - equals - 1); + + sal_Int32 j = 0; + sal_Bool first = sal_True; + for (sal_Int32 i = 0; i < length; i++) + { + if (implEntries.getConstArray()[i] != implName) + { + if (first) + { + oldImpl = implEntries.getConstArray()[i]; + first = sal_False; + } else + { + implEntriesNew.getArray()[j++] = implEntries.getConstArray()[i]; + } + } + } + + xOldKey->setAsciiListValue(implEntriesNew); + } else + { + oldImpl = implEntries.getConstArray()[0]; + rtl::OUString path(xOldKey->getKeyName()); + xOldKey->closeKey(); + xRootKey->deleteKey(path); + } + + OUString oldTarget = searchLinkTargetForImpl(xRootKey, linkName, oldImpl); + if (oldTarget.getLength()) + { + xRootKey->createLink(linkName, oldTarget); + } + } + + if (hasNoImplementations) + { + bClean = sal_True; + hasNoImplementations = sal_False; + rtl::OUString path(xOldKey->getKeyName()); + xOldKey->closeKey(); + xRootKey->deleteKey(path); + } + } + } else + { + bClean = sal_True; + } + + if (bClean) + { + OUString tmpName(linkName); + OUString path = tmpName.copy(0, tmpName.lastIndexOf('/')); + deletePathIfPossible(xRootKey, path); + } +} + +//************************************************************************* +// static prepareUserKeys +// +static void prepareUserKeys(const Reference < XSimpleRegistry >& xDest, + const Reference < XRegistryKey >& xUnoKey, + const Reference < XRegistryKey >& xKey, + const OUString& implName, + sal_Bool bRegister) + // throw ( InvalidRegistryException, RuntimeException ) +{ + sal_Bool hasSubKeys = sal_False; + + Sequence<OUString> keyNames = xKey->getKeyNames(); + + OUString relativKey; + if (keyNames.getLength()) + relativKey = keyNames.getConstArray()[0].copy(xKey->getKeyName().getLength()+1); + + if (keyNames.getLength() == 1 && + xKey->getKeyType(relativKey) == RegistryKeyType_LINK) + { + hasSubKeys = sal_True; + + OUString linkTarget = xKey->getLinkTarget(relativKey); + OUString linkName(xKey->getKeyName().copy(xUnoKey->getKeyName().getLength())); + + linkName = linkName + OUString( RTL_CONSTASCII_USTRINGPARAM("/") ) + relativKey; + + if (bRegister) + { + prepareUserLink(xDest, linkName, linkTarget, implName); + } else + { + deleteUserLink(xDest->getRootKey(), linkName, linkTarget, implName); + } + } else + { + Sequence< Reference < XRegistryKey> > subKeys = xKey->openKeys(); + + if (subKeys.getLength()) + { + hasSubKeys = sal_True; + const Reference < XRegistryKey > * pSubKeys = subKeys.getConstArray(); + + for (sal_Int32 i = 0; i < subKeys.getLength(); i++) + { + prepareUserKeys(xDest, xUnoKey, pSubKeys[i], implName, bRegister); + } + } + } + + if (! hasSubKeys) + { + OUString keyName(xKey->getKeyName().copy(xUnoKey->getKeyName().getLength())); + + Reference < XRegistryKey > xRootKey = xDest->getRootKey(); + if (bRegister) + { + createUniqueSubEntry(xRootKey->createKey(keyName), implName); + } + else + { + Reference< XRegistryKey > rKey = xRootKey->openKey(keyName); + if( rKey.is() ) + { + deleteSubEntry(rKey, implName); + xRootKey->deleteKey(keyName); + } + + OUString path = keyName.copy(0, keyName.lastIndexOf('/')); + if( path.getLength() ) + { + deletePathIfPossible(xRootKey, path); + } + } + } + return; +} + +//************************************************************************* +// static deleteAllImplementations +// +static void deleteAllImplementations( const Reference < XSimpleRegistry >& xReg, + const Reference < XRegistryKey >& xSource, + const OUString& locationUrl, + std::list<OUString> & implNames) + // throw (InvalidRegistryException, RuntimeException) +{ + Sequence < Reference < XRegistryKey > > subKeys = xSource->openKeys(); + + if (subKeys.getLength() > 0) + { + const Reference < XRegistryKey> * pSubKeys = subKeys.getConstArray(); + Reference < XRegistryKey > xImplKey; + sal_Bool hasLocationUrl = sal_False; + + const StringPool &pool = spool(); + for (sal_Int32 i = 0; i < subKeys.getLength(); i++) + { + xImplKey = pSubKeys[i]; + Reference < XRegistryKey > xKey = xImplKey->openKey( + pool.slash_UNO_slash_LOCATION ); + + if (xKey.is() && (xKey->getValueType() == RegistryValueType_ASCII)) + { + if (xKey->getAsciiValue() == locationUrl) + { + hasLocationUrl = sal_True; + + OUString implName(xImplKey->getKeyName().getStr() + 1); + sal_Int32 firstDot = implName.indexOf('/'); + + if (firstDot >= 0) + implName = implName.copy(firstDot + 1); + + implNames.push_back(implName); + + deleteAllLinkReferences(xReg, xImplKey); + + xKey = xImplKey->openKey( pool.slash_UNO ); + if (xKey.is()) + { + Sequence< Reference < XRegistryKey > > subKeys2 = xKey->openKeys(); + + if (subKeys2.getLength()) + { + const Reference < XRegistryKey > * pSubKeys2 = subKeys2.getConstArray(); + + for (sal_Int32 j = 0; j < subKeys2.getLength(); j++) + { + if (pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_SERVICES ) && + pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_REGISTRY_LINKS ) && + pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_ACTIVATOR ) && + pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_SINGLETONS ) && + pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_LOCATION) ) + { + prepareUserKeys(xReg, xKey, pSubKeys2[j], implName, sal_False); + } + } + } + } + } + } + + if (hasLocationUrl) + { + hasLocationUrl = sal_False; + rtl::OUString path(xImplKey->getKeyName()); + xImplKey->closeKey(); + xReg->getRootKey()->deleteKey(path); + } + } + + subKeys = xSource->openKeys(); + if (subKeys.getLength() == 0) + { + rtl::OUString path(xSource->getKeyName()); + xSource->closeKey(); + xReg->getRootKey()->deleteKey(path); + } + } else + { + rtl::OUString path(xSource->getKeyName()); + xSource->closeKey(); + xReg->getRootKey()->deleteKey(path); + } +} + +//================================================================================================== +static void delete_all_singleton_entries( + Reference < registry::XRegistryKey > const & xSingletons_section, + ::std::list< OUString > const & impl_names ) + // throw (InvalidRegistryException, RuntimeException) +{ + Sequence< Reference< registry::XRegistryKey > > singletons( xSingletons_section->openKeys() ); + Reference< registry::XRegistryKey > const * subkeys = singletons.getConstArray(); + for ( sal_Int32 nPos = singletons.getLength(); nPos--; ) + { + Reference< registry::XRegistryKey > const & xSingleton = subkeys[ nPos ]; + Reference< registry::XRegistryKey > xRegisteredImplNames( + xSingleton->openKey( OUSTR("REGISTERED_BY") ) ); + if (xRegisteredImplNames.is() && xRegisteredImplNames->isValid()) + { + Sequence< OUString > registered_implnames; + try + { + registered_implnames = xRegisteredImplNames->getAsciiListValue(); + } + catch (registry::InvalidValueException &) + { + } + OUString const * p = registered_implnames.getConstArray(); + sal_Int32 nOrigRegLength = registered_implnames.getLength(); + sal_Int32 nNewLength = nOrigRegLength; + for ( sal_Int32 n = nOrigRegLength; n--; ) + { + OUString const & registered_implname = p[ n ]; + + ::std::list< OUString >::const_iterator iPos( impl_names.begin() ); + ::std::list< OUString >::const_iterator const iEnd( impl_names.end() ); + for ( ; iPos != iEnd; ++iPos ) + { + if (iPos->equals( registered_implname )) + { + registered_implnames[ n ] = p[ nNewLength -1 ]; + --nNewLength; + } + } + } + + if (nNewLength != nOrigRegLength) + { + if (0 == nNewLength) + { + // remove whole entry + xRegisteredImplNames->closeKey(); + xSingleton->deleteKey( OUSTR("REGISTERED_BY") ); + // registry key cannot provide its relative name, only absolute :( + OUString abs( xSingleton->getKeyName() ); + xSingletons_section->deleteKey( abs.copy( abs.lastIndexOf( '/' ) +1 ) ); + } + else + { + registered_implnames.realloc( nNewLength ); + xRegisteredImplNames->setAsciiListValue( registered_implnames ); + } + } + } + } +} + +//************************************************************************* +// static deleteAllServiceEntries +// +static void deleteAllServiceEntries( const Reference < XSimpleRegistry >& xReg, + const Reference < XRegistryKey >& xSource, + const OUString& implName) + // throw ( InvalidRegistryException, RuntimeException ) +{ + Sequence< Reference < XRegistryKey > > subKeys = xSource->openKeys(); + + if (subKeys.getLength() > 0) + { + const Reference < XRegistryKey > * pSubKeys = subKeys.getConstArray(); + Reference < XRegistryKey > xServiceKey; + sal_Bool hasNoImplementations = sal_False; + + for (sal_Int32 i = 0; i < subKeys.getLength(); i++) + { + xServiceKey = pSubKeys[i]; + + if (xServiceKey->getValueType() == RegistryValueType_ASCIILIST) + { + Sequence<OUString> implEntries = xServiceKey->getAsciiListValue(); + sal_Int32 length = implEntries.getLength(); + sal_Int32 equals = 0; + + for (sal_Int32 j = 0; j < length; j++) + { + if (implEntries.getConstArray()[j] == implName) + equals++; + } + + if (equals == length) + { + hasNoImplementations = sal_True; + } else + { + if (equals > 0) + { + Sequence<OUString> implEntriesNew(length-equals); + + sal_Int32 j = 0; + for (sal_Int32 k = 0; k < length; k++) + { + if (implEntries.getConstArray()[k] != implName) + { + implEntriesNew.getArray()[j++] = implEntries.getConstArray()[k]; + } + } + + xServiceKey->setAsciiListValue(implEntriesNew); + } + } + } + + if (hasNoImplementations) + { + hasNoImplementations = sal_False; + rtl::OUString path(xServiceKey->getKeyName()); + xServiceKey->closeKey(); + xReg->getRootKey()->deleteKey(path); + } + } + + subKeys = xSource->openKeys(); + if (subKeys.getLength() == 0) + { + rtl::OUString path(xSource->getKeyName()); + xSource->closeKey(); + xReg->getRootKey()->deleteKey(path); + } + } else + { + rtl::OUString path(xSource->getKeyName()); + xSource->closeKey(); + xReg->getRootKey()->deleteKey(path); + } +} + +//-------------------------------------------------------------------------------------------------- +static bool is_supported_service( + OUString const & service_name, + Reference< reflection::XServiceTypeDescription > const & xService_td ) +{ + if (xService_td->getName().equals( service_name )) + return true; + Sequence< Reference< reflection::XServiceTypeDescription > > seq( + xService_td->getMandatoryServices() ); + Reference< reflection::XServiceTypeDescription > const * p = seq.getConstArray(); + for ( sal_Int32 nPos = seq.getLength(); nPos--; ) + { + if (is_supported_service( service_name, p[ nPos ] )) + return true; + } + return false; +} + +//-------------------------------------------------------------------------------------------------- +static void insert_singletons( + Reference< registry::XSimpleRegistry > const & xDest, + Reference< registry::XRegistryKey > const & xImplKey, + Reference< XComponentContext > const & xContext ) + // throw( registry::InvalidRegistryException, registry::CannotRegisterImplementationException, RuntimeException ) +{ + // singletons + Reference< registry::XRegistryKey > xKey( xImplKey->openKey( OUSTR("UNO/SINGLETONS") ) ); + if (xKey.is() && xKey->isValid()) + { + OUString implname( xImplKey->getKeyName().copy( sizeof ("/IMPLEMENTATIONS/") -1 ) ); + // singleton entries + Sequence< Reference< registry::XRegistryKey > > xSingletons_section( xKey->openKeys() ); + Reference< registry::XRegistryKey > const * p = xSingletons_section.getConstArray(); + for ( sal_Int32 nPos = xSingletons_section.getLength(); nPos--; ) + { + Reference< registry::XRegistryKey > const & xSingleton = p[ nPos ]; + OUString singleton_name( + xSingleton->getKeyName().copy( + implname.getLength() + sizeof ("/IMPLEMENTATIONS//UNO/SINGLETONS/") -1 ) ); + OUString service_name( xSingleton->getStringValue() ); + + OUString keyname( OUSTR("/SINGLETONS/") + singleton_name ); + Reference< registry::XRegistryKey > xKey2( xDest->getRootKey()->openKey( keyname ) ); + if (xKey2.is() && xKey2->isValid()) + { + try + { + OUString existing_name( xKey2->getStringValue() ); + if (! existing_name.equals( service_name )) + { + Reference< container::XHierarchicalNameAccess > xTDMgr; + OUString the_tdmgr = + OUSTR("/singletons/com.sun.star.reflection.theTypeDescriptionManager"); + xContext->getValueByName( the_tdmgr ) >>= xTDMgr; + if (! xTDMgr.is()) + { + throw RuntimeException( + OUSTR("cannot get singleton ") + the_tdmgr, + Reference< XInterface >() ); + } + try + { + Reference< reflection::XServiceTypeDescription > xExistingService_td; + xTDMgr->getByHierarchicalName( existing_name ) >>= xExistingService_td; + if (! xExistingService_td.is()) + { + throw RuntimeException( + OUSTR("cannot get service type description: ") + existing_name, + Reference< XInterface >() ); + } + + // everything's fine if existing service entry supports the one + // to be registered + if (! is_supported_service( service_name, xExistingService_td )) + { + OUStringBuffer buf( 64 ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("existing singleton service (") ); + buf.append( singleton_name ); + buf.append( (sal_Unicode)'=' ); + buf.append( existing_name ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM(") does not support given one: ") ); + buf.append( service_name ); + throw registry::CannotRegisterImplementationException( + buf.makeStringAndClear(), Reference< XInterface >() ); + } + } + catch (container::NoSuchElementException & exc) + { + throw RuntimeException( + OUSTR("cannot get service type description: ") + exc.Message, + Reference< XInterface >() ); + } + } + } + catch (registry::InvalidValueException &) + { + // repair + xKey2->setStringValue( service_name ); + } + } + else + { + // insert singleton entry + xKey2 = xDest->getRootKey()->createKey( keyname ); + xKey2->setStringValue( service_name ); + } + + Reference< registry::XRegistryKey > xRegisteredImplNames( + xKey2->openKey( OUSTR("REGISTERED_BY") ) ); + if (!xRegisteredImplNames.is() || !xRegisteredImplNames->isValid()) + { + // create + xRegisteredImplNames = xKey2->createKey( OUSTR("REGISTERED_BY") ); + } + + Sequence< OUString > implnames; + try + { + implnames = xRegisteredImplNames->getAsciiListValue(); + } + catch (registry::InvalidValueException &) + { + } + // check implname is already in + sal_Int32 nPos_implnames = implnames.getLength(); + OUString const * pImplnames = implnames.getConstArray(); + while (nPos_implnames--) + { + if (implname.equals( pImplnames[ nPos_implnames ] )) + break; + } + if (nPos_implnames < 0) + { + // append and write back + implnames.realloc( implnames.getLength() +1 ); + implnames[ implnames.getLength() -1 ] = implname; + xRegisteredImplNames->setAsciiListValue( implnames ); + } + } + } +} + + +//************************************************************************* +// static prepareRegistry +// +static void prepareRegistry( + const Reference < XSimpleRegistry >& xDest, + const Reference < XRegistryKey >& xSource, + const OUString& implementationLoaderUrl, + const OUString& locationUrl, + Reference< XComponentContext > const & xContext ) + // throw ( InvalidRegistryException, CannotRegisterImplementationException, RuntimeException ) +{ + Sequence< Reference < XRegistryKey > > subKeys = xSource->openKeys(); + + if (!subKeys.getLength()) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM( "prepareRegistry(): source registry is empty" ) ), + Reference< XInterface > () ); + } + + const StringPool & pool = spool(); + + const Reference < XRegistryKey >* pSubKeys = subKeys.getConstArray(); + Reference < XRegistryKey > xImplKey; + + for (sal_Int32 i = 0; i < subKeys.getLength(); i++) + { + xImplKey = pSubKeys[i]; + + Reference < XRegistryKey > xKey = xImplKey->openKey( + pool.slash_UNO_slash_SERVICES ); + + if (xKey.is()) + { + // update entries in SERVICES section + Sequence< Reference < XRegistryKey > > serviceKeys = xKey->openKeys(); + const Reference < XRegistryKey > * pServiceKeys = serviceKeys.getConstArray(); + + OUString implName = OUString(xImplKey->getKeyName().getStr() + 1); + sal_Int32 firstDot = implName.indexOf('/'); + + if (firstDot >= 0) + implName = implName.copy(firstDot + 1); + + sal_Int32 offset = xKey->getKeyName().getLength() + 1; + + for (sal_Int32 j = 0; j < serviceKeys.getLength(); j++) + { + OUString serviceName = pServiceKeys[j]->getKeyName().copy(offset); + + createUniqueSubEntry( + xDest->getRootKey()->createKey( + pool.slash_SERVICES + serviceName ), + implName); + } + + xKey = xImplKey->openKey( pool.slash_UNO ); + if (xKey.is()) + { + Sequence< Reference < XRegistryKey > > subKeys2 = xKey->openKeys(); + + if (subKeys2.getLength()) + { + const Reference < XRegistryKey > * pSubKeys2 = subKeys2.getConstArray(); + + for (sal_Int32 j = 0; j < subKeys2.getLength(); j++) + { + if (pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_SERVICES) && + pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_REGISTRY_LINKS ) && + pSubKeys2[j]->getKeyName() != (xImplKey->getKeyName() + pool.slash_UNO_slash_SINGLETONS )) + { + prepareUserKeys(xDest, xKey, pSubKeys2[j], implName, sal_True); + } + } + } + } + } + + // update LOCATION entry + xKey = xImplKey->createKey( pool.slash_UNO_slash_LOCATION ); + + if (xKey.is()) + { + xKey->setAsciiValue(locationUrl); + } + + // update ACTIVATOR entry + xKey = xImplKey->createKey( pool.slash_UNO_slash_ACTIVATOR ); + + if (xKey.is()) + { + xKey->setAsciiValue(implementationLoaderUrl); + } + + xKey = xImplKey->openKey( pool.slash_UNO_slash_SERVICES ); + + if (xKey.is() && (xKey->getValueType() == RegistryValueType_ASCIILIST)) + { + // update link entries in REGISTRY_LINKS section + Sequence<OUString> linkNames = xKey->getAsciiListValue(); + + if (linkNames.getLength()) + { + const OUString* pLinkNames = linkNames.getConstArray(); + + for (sal_Int32 j = 0; j < linkNames.getLength(); j++) + { + prepareLink(xDest, xImplKey, pLinkNames[j]); + } + } + } + + insert_singletons( xDest, xImplKey, xContext ); + } +} + + +static void findImplementations( const Reference < XRegistryKey > & xSource, + std::list <OUString>& implNames) +{ + sal_Bool isImplKey = sal_False; + + try + { + Reference < XRegistryKey > xKey = xSource->openKey( + spool().slash_UNO_slash_SERVICES ); + + if (xKey.is() && (xKey->getKeyNames().getLength() > 0)) + { + isImplKey = sal_True; + + OUString implName = OUString(xSource->getKeyName().getStr() + 1).replace('/', '.').getStr(); + sal_Int32 firstDot = implName.indexOf('.'); + + if (firstDot >= 0) + implName = implName.copy(firstDot + 1); + + implNames.push_back(implName); + } + } + catch(InvalidRegistryException&) + { + } + + if (isImplKey) return; + + try + { + Sequence< Reference < XRegistryKey > > subKeys = xSource->openKeys(); + + if (subKeys.getLength() > 0) + { + const Reference < XRegistryKey >* pSubKeys = subKeys.getConstArray(); + + for (sal_Int32 i = 0; i < subKeys.getLength(); i++) + { + findImplementations(pSubKeys[i], implNames); + } + + } + } + catch(InvalidRegistryException&) + { + } +} + + +class ImplementationRegistration + : public WeakImplHelper3< XImplementationRegistration2, XServiceInfo, XInitialization > +{ +public: + ImplementationRegistration( const Reference < XComponentContext > & rSMgr ); + ~ImplementationRegistration(); + + // XServiceInfo + OUString SAL_CALL getImplementationName() throw(RuntimeException); + sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw(RuntimeException); + Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw(RuntimeException); + + // XImplementationRegistration + virtual void SAL_CALL registerImplementation( + const OUString& implementationLoader, + const OUString& location, + const Reference < XSimpleRegistry > & xReg) + throw( CannotRegisterImplementationException, RuntimeException ); + + virtual sal_Bool SAL_CALL revokeImplementation( + const OUString& location, + const Reference < XSimpleRegistry >& xReg) + throw( RuntimeException ); + + virtual Sequence< OUString > SAL_CALL getImplementations( + const OUString& implementationLoader, + const OUString& location) + throw( RuntimeException ); + virtual Sequence< OUString > SAL_CALL checkInstantiation( + const OUString& implementationName) + throw( RuntimeException ); + + // XImplementationRegistration2 + virtual void SAL_CALL registerImplementationWithLocation( + const OUString& implementationLoader, + const OUString& location, + const OUString& registeredLocation, + const Reference < XSimpleRegistry > & xReg) + throw( CannotRegisterImplementationException, RuntimeException ); + + // XInitialization + virtual void SAL_CALL initialize( + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw( ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + +private: // helper methods + void prepareRegister( + const OUString& implementationLoader, + const OUString& location, + const OUString& registeredLocation, + const Reference < XSimpleRegistry > & xReg); + // throw( CannotRegisterImplementationException, RuntimeException ) + + static void doRegister( const Reference < XMultiComponentFactory >& xSMgr, + const Reference < XComponentContext > &xCtx, + const Reference < XImplementationLoader >& xAct, + const Reference < XSimpleRegistry >& xDest, + const OUString& implementationLoaderUrl, + const OUString& locationUrl, + const OUString& registeredLocationUrl); + /* throw ( InvalidRegistryException, + MergeConflictException, + CannotRegisterImplementationException, RuntimeException ) */ + + static void doRevoke( const Reference < XSimpleRegistry >& xDest, + const OUString& locationUrl ); + // throw( InvalidRegistryException, RuntimeException ) + Reference< XSimpleRegistry > getRegistryFromServiceManager(); + + static Reference< XSimpleRegistry > createTemporarySimpleRegistry( + const Reference< XMultiComponentFactory > &rSMgr, + const Reference < XComponentContext > & rCtx ); + +private: // members + Reference < XMultiComponentFactory > m_xSMgr; + Reference < XComponentContext > m_xCtx; +}; + +//************************************************************************* +// ImplementationRegistration() +// +ImplementationRegistration::ImplementationRegistration( const Reference < XComponentContext > & xCtx ) + : m_xSMgr( xCtx->getServiceManager() ) + , m_xCtx( xCtx ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); +} + +//************************************************************************* +// ~ImplementationRegistration() +// +ImplementationRegistration::~ImplementationRegistration() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + + +// XServiceInfo +OUString ImplementationRegistration::getImplementationName() throw(RuntimeException) +{ + return stoc_bootstrap::impreg_getImplementationName(); +} + +// XServiceInfo +sal_Bool ImplementationRegistration::supportsService(const OUString& ServiceName) throw(RuntimeException) +{ + Sequence< OUString > aSNL = getSupportedServiceNames(); + const OUString * pArray = aSNL.getConstArray(); + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return sal_True; + return sal_False; +} + +// XServiceInfo +Sequence< OUString > ImplementationRegistration::getSupportedServiceNames(void) throw(RuntimeException) +{ + return stoc_bootstrap::impreg_getSupportedServiceNames(); +} + +Reference< XSimpleRegistry > ImplementationRegistration::getRegistryFromServiceManager() +{ + Reference < XPropertySet > xPropSet( m_xSMgr, UNO_QUERY ); + Reference < XSimpleRegistry > xRegistry; + + if( xPropSet.is() ) { + + try { // the implementation does not support XIntrospectionAccess ! + + Any aAny = xPropSet->getPropertyValue( spool().Registry ); + + if( aAny.getValueType().getTypeClass() == TypeClass_INTERFACE ) { + aAny >>= xRegistry; + } + } + catch( UnknownPropertyException & ) { + // empty reference is error signal ! + } + } + + return xRegistry; +} + + +//************************************************************************ +// XInitialization +// +void ImplementationRegistration::initialize( + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArgs ) + throw( ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + + if( aArgs.getLength() != 4 ) { + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "ImplementationRegistration::initialize() expects 4 parameters, got ")); + buf.append( (sal_Int32) aArgs.getLength() ); + throw IllegalArgumentException( buf.makeStringAndClear(), + Reference<XInterface > (), + 0 ); + } + + Reference< XImplementationLoader > rLoader; + OUString loaderServiceName; + OUString locationUrl; + Reference< XSimpleRegistry > rReg; + + // 1st argument : An instance of an implementation loader + if( aArgs.getConstArray()[0].getValueType().getTypeClass() == TypeClass_INTERFACE ) { + aArgs.getConstArray()[0] >>= rLoader; + } + if( !rLoader.is()) { + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "ImplementationRegistration::initialize() invalid first parameter," + "expected " ) ); + buf.append( getCppuType( &rLoader ).getTypeName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ", got " ) ); + buf.append( aArgs.getConstArray()[0].getValueTypeName() ); + throw IllegalArgumentException( buf.makeStringAndClear(), + Reference< XInterface > (), + 0 ); + } + + // 2nd argument : The service name of the loader. This name is written into the registry + if( aArgs.getConstArray()[1].getValueType().getTypeClass() == TypeClass_STRING ) { + aArgs.getConstArray()[1] >>= loaderServiceName; + } + if( ! loaderServiceName.getLength() ) { + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "ImplementationRegistration::initialize() invalid second parameter," + "expected string, got " ) ); + buf.append( aArgs.getConstArray()[1].getValueTypeName() ); + throw IllegalArgumentException( buf.makeStringAndClear(), + Reference< XInterface > (), + 0 ); + } + + // 3rd argument : The file name of the dll, that contains the loader + if( aArgs.getConstArray()[2].getValueType().getTypeClass() == TypeClass_STRING ) { + aArgs.getConstArray()[2] >>= locationUrl; + } + if( ! locationUrl.getLength() ) { + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "ImplementationRegistration::initialize() invalid third parameter," + "expected string, got " ) ); + buf.append( aArgs.getConstArray()[2].getValueTypeName() ); + throw IllegalArgumentException( buf.makeStringAndClear(), + Reference< XInterface > (), + 0 ); + } + + // 4th argument : The registry, the service should be written to + if( aArgs.getConstArray()[3].getValueType().getTypeClass() == TypeClass_INTERFACE ) { + aArgs.getConstArray()[3] >>= rReg; + } + + if( !rReg.is() ) { + rReg = getRegistryFromServiceManager(); + if( !rReg.is() ) { + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "ImplementationRegistration::initialize() invalid fourth parameter," + "expected " )); + buf.append( getCppuType( &rReg ).getTypeName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", got " ) ); + buf.append( aArgs.getConstArray()[3].getValueTypeName() ); + throw IllegalArgumentException( buf.makeStringAndClear(), + Reference< XInterface > (), + 0 ); + } + } + + doRegister(m_xSMgr, m_xCtx, rLoader , rReg, loaderServiceName , locationUrl, locationUrl); +} + + + +//************************************************************************* +// virtual function registerImplementationWithLocation of XImplementationRegistration2 +// +void ImplementationRegistration::registerImplementationWithLocation( + const OUString& implementationLoaderUrl, + const OUString& locationUrl, + const OUString& registeredLocationUrl, + const Reference < XSimpleRegistry > & xReg) + throw( CannotRegisterImplementationException, RuntimeException ) +{ + prepareRegister( + implementationLoaderUrl, locationUrl, registeredLocationUrl, xReg); +} + +// helper function +void ImplementationRegistration::prepareRegister( + const OUString& implementationLoaderUrl, + const OUString& locationUrl, + const OUString& registeredLocationUrl, + const Reference < XSimpleRegistry > & xReg) + // throw( CannotRegisterImplementationException, RuntimeException ) +{ + OUString implLoaderUrl(implementationLoaderUrl); + OUString activatorName; + + if (implementationLoaderUrl.getLength() > 0) + { + OUString tmpActivator(implementationLoaderUrl); + sal_Int32 nIndex = 0; + activatorName = tmpActivator.getToken(0, ':', nIndex ); + } else + { + // check locationUrl to find out what kind of loader is needed + // set iimplLoaderUrl + } + + if( m_xSMgr.is() ) { + try + { + Reference < XImplementationLoader > xAct( + m_xSMgr->createInstanceWithContext(activatorName, m_xCtx) , UNO_QUERY ); + if (xAct.is()) + { + Reference < XSimpleRegistry > xRegistry; + + if (xReg.is()) + { + // registry supplied by user + xRegistry = xReg; + } + else + { + xRegistry = getRegistryFromServiceManager(); + } + + if ( xRegistry.is()) + { + doRegister(m_xSMgr, m_xCtx, xAct, xRegistry, implLoaderUrl, + locationUrl, registeredLocationUrl); + } + } + else + { + OUStringBuffer buf( 128 ); + buf.appendAscii( "ImplementationRegistration::registerImplementation() - The service " ); + buf.append( activatorName ); + buf.appendAscii( " cannot be instantiated\n" ); + throw CannotRegisterImplementationException( + buf.makeStringAndClear(), Reference< XInterface > () ); + } + } + catch( CannotRegisterImplementationException & ) + { + throw; + } + catch( InvalidRegistryException & e ) + { + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "ImplementationRegistration::registerImplementation() " + "InvalidRegistryException during registration (" )); + buf.append( e.Message ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ")" ) ); + throw CannotRegisterImplementationException( + buf.makeStringAndClear(), Reference< XInterface > () ); + } + catch( MergeConflictException & e ) + { + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "ImplementationRegistration::registerImplementation() " + "MergeConflictException during registration (" )); + buf.append( e.Message ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( ")" ) ); + throw CannotRegisterImplementationException( + buf.makeStringAndClear(), Reference< XInterface > () ); + } + } + else + { + throw CannotRegisterImplementationException( + OUString(RTL_CONSTASCII_USTRINGPARAM( + "ImplementationRegistration::registerImplementation() " + "no componentcontext available to instantiate loader")), + Reference< XInterface > () ); + } +} + +//************************************************************************* +// virtual function registerImplementation of XImplementationRegistration +// +void ImplementationRegistration::registerImplementation( + const OUString& implementationLoaderUrl, + const OUString& locationUrl, + const Reference < XSimpleRegistry > & xReg) + throw( CannotRegisterImplementationException, RuntimeException ) +{ + prepareRegister(implementationLoaderUrl, locationUrl, locationUrl, xReg); +} + + +//************************************************************************* +// virtual function revokeImplementation of XImplementationRegistration +// +sal_Bool ImplementationRegistration::revokeImplementation(const OUString& location, + const Reference < XSimpleRegistry >& xReg) + throw ( RuntimeException ) +{ + sal_Bool ret = sal_False; + + Reference < XSimpleRegistry > xRegistry; + + if (xReg.is()) { + xRegistry = xReg; + } + else { + Reference < XPropertySet > xPropSet = Reference< XPropertySet >::query( m_xSMgr ); + if( xPropSet.is() ) { + try { + Any aAny = xPropSet->getPropertyValue( spool().Registry ); + + if( aAny.getValueType().getTypeClass() == TypeClass_INTERFACE ) + { + aAny >>= xRegistry; + } + } + catch ( UnknownPropertyException & ) { + } + } + } + + if (xRegistry.is()) + { + try + { + doRevoke(xRegistry, location); + ret = sal_True; + } + catch( InvalidRegistryException & ) + { + // no way to transport the error, as no exception is specified and a runtime + // exception is not appropriate. + OSL_ENSURE( 0 , "InvalidRegistryException during revokeImplementation" ); + } + } + + return ret; +} + +//************************************************************************* +// virtual function getImplementations of XImplementationRegistration +// +Sequence< OUString > ImplementationRegistration::getImplementations( + const OUString & implementationLoaderUrl, + const OUString & locationUrl) + throw ( RuntimeException ) +{ + OUString implLoaderUrl(implementationLoaderUrl); + OUString activatorName; + + if (implementationLoaderUrl.getLength() > 0) + { + OUString tmpActivator(implementationLoaderUrl); + sal_Int32 nIndex = 0; + activatorName = tmpActivator.getToken(0, ':', nIndex ); + } else + { + // check locationUrl to find out what kind of loader is needed + // set implLoaderUrl + } + + if( m_xSMgr.is() ) { + + Reference < XImplementationLoader > xAct( + m_xSMgr->createInstanceWithContext( activatorName, m_xCtx ), UNO_QUERY ); + + if (xAct.is()) + { + + Reference < XSimpleRegistry > xReg = + createTemporarySimpleRegistry( m_xSMgr, m_xCtx); + + if (xReg.is()) + { + try + { + xReg->open(OUString() /* in mem */, sal_False, sal_True); + Reference < XRegistryKey > xImpl; + + { // only necessary for deleting the temporary variable of rootkey + xImpl = xReg->getRootKey()->createKey( spool().slash_IMPLEMENTATIONS ); + } + if (xAct->writeRegistryInfo(xImpl, implementationLoaderUrl, locationUrl)) + { + std::list <OUString> implNames; + + findImplementations(xImpl, implNames); + + if (!implNames.empty()) + { + std::list<OUString>::const_iterator iter = implNames.begin(); + + Sequence<OUString> seqImpl(implNames.size()); + OUString *pImplNames = seqImpl.getArray(); + + sal_Int32 index = 0; + while (iter != implNames.end()) + { + pImplNames[index] = *iter; + index++; + ++iter; + } + + xImpl->closeKey(); + return seqImpl; + } + } + + xImpl->closeKey(); + } + catch(MergeConflictException&) + { + } + catch(InvalidRegistryException&) + { + } + } + } + } + + return Sequence<OUString>(); +} + +//************************************************************************* +// virtual function checkInstantiation of XImplementationRegistration +// +Sequence< OUString > ImplementationRegistration::checkInstantiation(const OUString&) + throw ( RuntimeException ) +{ + OSL_ENSURE( sal_False, "ImplementationRegistration::checkInstantiation not implemented" ); + return Sequence<OUString>(); +} + +//************************************************************************* +// helper function doRegistration +// + +void ImplementationRegistration::doRevoke( + const Reference < XSimpleRegistry >& xDest, + const OUString& locationUrl) + // throw ( InvalidRegistryException, RuntimeException ) +{ + if( xDest.is() ) + { + std::list<OUString> aNames; + + const StringPool &pool = spool(); + Reference < XRegistryKey > xRootKey( xDest->getRootKey() ); + + Reference < XRegistryKey > xKey = + xRootKey->openKey( pool.slash_IMPLEMENTATIONS ); + if (xKey.is() && xKey->isValid()) + { + deleteAllImplementations(xDest, xKey, locationUrl, aNames); + } + + xKey = xRootKey->openKey( pool.slash_SERVICES ); + if (xKey.is()) + { + std::list<OUString>::const_iterator iter = aNames.begin(); + + while (iter != aNames.end()) + { + deleteAllServiceEntries(xDest, xKey, *iter); + ++iter; + } + } + + xKey = xRootKey->openKey( OUSTR("/SINGLETONS") ); + if (xKey.is() && xKey->isValid()) + { + delete_all_singleton_entries( xKey, aNames ); + } + + if (xRootKey.is()) + xRootKey->closeKey(); + if (xKey.is() && xKey->isValid() ) + xKey->closeKey(); + } +} + +void ImplementationRegistration::doRegister( + const Reference< XMultiComponentFactory > & xSMgr, + const Reference< XComponentContext > &xCtx, + const Reference < XImplementationLoader > & xAct, + const Reference < XSimpleRegistry >& xDest, + const OUString& implementationLoaderUrl, + const OUString& locationUrl, + const OUString& registeredLocationUrl) + /* throw ( InvalidRegistryException, + MergeConflictException, + CannotRegisterImplementationException, RuntimeException ) */ +{ + Reference < XSimpleRegistry > xReg = + createTemporarySimpleRegistry( xSMgr, xCtx ); + Reference < XRegistryKey > xSourceKey; + + if (xAct.is() && xReg.is() && xDest.is()) + { + try + { + xReg->open(OUString() /* in mem */, sal_False, sal_True); + + { // only necessary for deleting the temporary variable of rootkey + xSourceKey = xReg->getRootKey()->createKey( spool().slash_IMPLEMENTATIONS ); + } + + sal_Bool bSuccess = + xAct->writeRegistryInfo(xSourceKey, implementationLoaderUrl, locationUrl); + if ( bSuccess ) + { + prepareRegistry(xDest, xSourceKey, implementationLoaderUrl, registeredLocationUrl, xCtx); + + xSourceKey->closeKey(); + + xSourceKey = xReg->getRootKey(); + Reference < XRegistryKey > xDestKey = xDest->getRootKey(); + mergeKeys( xDestKey, xSourceKey ); + xDestKey->closeKey(); + xSourceKey->closeKey(); + } + else + { + throw CannotRegisterImplementationException( + OUString( RTL_CONSTASCII_USTRINGPARAM( "ImplementationRegistration::doRegistration() component registration signaled failure" ) ), + Reference< XInterface > () ); + } + + // Cleanup Source registry. + if ( xSourceKey->isValid() ) + xSourceKey->closeKey(); + } + catch(CannotRegisterImplementationException&) + { + if ( xSourceKey->isValid() ) + xSourceKey->closeKey(); + // and throw again + throw; + } + } +} + + + +Reference< XSimpleRegistry > ImplementationRegistration::createTemporarySimpleRegistry( + const Reference< XMultiComponentFactory > &rSMgr, + const Reference < XComponentContext > & xCtx) +{ + + Reference < XSimpleRegistry > xReg( + rSMgr->createInstanceWithContext( + spool().com_sun_star_registry_SimpleRegistry, xCtx ), + UNO_QUERY); + OSL_ASSERT( xReg.is() ); + return xReg; +} +} + +namespace stoc_bootstrap +{ +//************************************************************************* +Reference<XInterface> SAL_CALL ImplementationRegistration_CreateInstance( + const Reference<XComponentContext> & xCtx ) // throw(Exception) +{ + return (XImplementationRegistration *)new stoc_impreg::ImplementationRegistration(xCtx); +} + +} + diff --git a/stoc/source/implementationregistration/makefile.mk b/stoc/source/implementationregistration/makefile.mk new file mode 100644 index 000000000000..2de7fe91cb21 --- /dev/null +++ b/stoc/source/implementationregistration/makefile.mk @@ -0,0 +1,47 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME= stoc +TARGET = implreg +ENABLE_EXCEPTIONS=TRUE +BOOTSTRAP_SERVICE=TRUE +UNOUCROUT= $(OUT)$/inc$/bootstrap + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# ------------------------------------------------------------------ + +SLOFILES= \ + $(SLO)$/mergekeys.obj \ + $(SLO)$/implreg.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/stoc/source/implementationregistration/mergekeys.cxx b/stoc/source/implementationregistration/mergekeys.cxx new file mode 100644 index 000000000000..acfec677badf --- /dev/null +++ b/stoc/source/implementationregistration/mergekeys.cxx @@ -0,0 +1,186 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include <vector> + +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/registry/MergeConflictException.hpp> + +#include "mergekeys.hxx" + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + +using namespace ::rtl; +using namespace ::osl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star; + +namespace stoc_impreg +{ + +struct Link +{ + OUString m_name; + OUString m_target; + + inline Link( OUString const & name, OUString const & target ) + : m_name( name ) + , m_target( target ) + {} +}; +typedef ::std::vector< Link > t_links; + +//================================================================================================== +static void mergeKeys( + Reference< registry::XRegistryKey > const & xDest, + Reference< registry::XRegistryKey > const & xSource, + t_links & links ) + // throw( registry::InvalidRegistryException, registry::MergeConflictException, RuntimeException ) +{ + if (!xSource.is() || !xSource->isValid()) { + throw registry::InvalidRegistryException( + OUSTR("source key is null or invalid!"), + Reference<XInterface>() ); + } + if (!xDest.is() || !xDest->isValid()) { + throw registry::InvalidRegistryException( + OUSTR("destination key is null or invalid!"), + Reference<XInterface>() ); + } + + // write value + switch (xSource->getValueType()) + { + case registry::RegistryValueType_NOT_DEFINED: + break; + case registry::RegistryValueType_LONG: + xDest->setLongValue( xSource->getLongValue() ); + break; + case registry::RegistryValueType_ASCII: + xDest->setAsciiValue( xSource->getAsciiValue() ); + break; + case registry::RegistryValueType_STRING: + xDest->setStringValue( xSource->getStringValue() ); + break; + case registry::RegistryValueType_BINARY: + xDest->setBinaryValue( xSource->getBinaryValue() ); + break; + case registry::RegistryValueType_LONGLIST: + xDest->setLongListValue( xSource->getLongListValue() ); + break; + case registry::RegistryValueType_ASCIILIST: + xDest->setAsciiListValue( xSource->getAsciiListValue() ); + break; + case registry::RegistryValueType_STRINGLIST: + xDest->setStringListValue( xSource->getStringListValue() ); + break; + default: + OSL_ASSERT(false); + break; + } + + // sub keys + Sequence< OUString > sourceKeys( xSource->getKeyNames() ); + OUString const * pSourceKeys = sourceKeys.getConstArray(); + for ( sal_Int32 nPos = sourceKeys.getLength(); nPos--; ) + { + // key name + OUString name( pSourceKeys[ nPos ] ); + sal_Int32 nSlash = name.lastIndexOf( '/' ); + if (nSlash >= 0) + { + name = name.copy( nSlash +1 ); + } + + if (xSource->getKeyType( name ) == registry::RegistryKeyType_KEY) + { + // try to open exisiting dest key or create new one + Reference< registry::XRegistryKey > xDestKey( xDest->createKey( name ) ); + Reference< registry::XRegistryKey > xSourceKey( xSource->openKey( name ) ); + mergeKeys( xDestKey, xSourceKey, links ); + xSourceKey->closeKey(); + xDestKey->closeKey(); + } + else // link + { + // remove existing key + Reference< registry::XRegistryKey > xDestKey( xDest->openKey( name ) ); + if (xDestKey.is() && xDestKey->isValid()) // something to remove + { + xDestKey->closeKey(); + if (xDest->getKeyType( name ) == registry::RegistryKeyType_LINK) + { + xDest->deleteLink( name ); + } + else + { + xDest->deleteKey( name ); + } + } + + links.push_back( Link( + pSourceKeys[ nPos ], // abs path + xSource->getResolvedName( name ) // abs resolved name + ) ); + } + } +} + +//================================================================================================== +void mergeKeys( + Reference< registry::XRegistryKey > const & xDest, + Reference< registry::XRegistryKey > const & xSource ) + // throw( registry::InvalidRegistryException, registry::MergeConflictException, RuntimeException ) +{ + if (!xDest.is() || !xDest->isValid()) { + throw registry::InvalidRegistryException( + OUSTR("destination key is null or invalid!"), + Reference<XInterface>() ); + } + if (xDest->isReadOnly()) + { + throw registry::InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "destination registry is read-only! cannot merge!") ), + Reference< XInterface >() ); + } + + t_links links; + links.reserve( 16 ); + mergeKeys( xDest, xSource, links ); + + for ( size_t nPos = links.size(); nPos--; ) + { + Link const & r = links[ nPos ]; + OSL_VERIFY( xDest->createLink( r.m_name, r.m_target ) ); + } +} + +} diff --git a/stoc/source/implementationregistration/mergekeys.hxx b/stoc/source/implementationregistration/mergekeys.hxx new file mode 100644 index 000000000000..3a8bd177b56d --- /dev/null +++ b/stoc/source/implementationregistration/mergekeys.hxx @@ -0,0 +1,52 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_STOC_SOURCE_IMPLEMENTATIONREGISTRATION_MERGEKEYS_HXX +#define INCLUDED_STOC_SOURCE_IMPLEMENTATIONREGISTRATION_MERGEKEYS_HXX + +#include "sal/config.h" + +#include "com/sun/star/uno/Reference.hxx" + +namespace com { namespace sun { namespace star { namespace registry { + class XRegistryKey; +} } } } + +namespace stoc_impreg { + +// throws ::com::sun::star::registry::InvalidRegistryException, +// ::com::sun::star::registry::MergeConflictException, +// ::com::sun::star::uno::RuntimeException: +void mergeKeys( + ::com::sun::star::uno::Reference< ::com::sun::star::registry::XRegistryKey > + const & xDest, + ::com::sun::star::uno::Reference< ::com::sun::star::registry::XRegistryKey > + const & xSource); + +} + +#endif diff --git a/stoc/source/inspect/insp.xml b/stoc/source/inspect/insp.xml new file mode 100644 index 000000000000..48b46d273cb1 --- /dev/null +++ b/stoc/source/inspect/insp.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + <module-name> introspection.uno </module-name> + <component-description> + <author> Juergen Schmidt </author> + <name> com.sun.star.comp.stoc.Introspection </name> + <description> + This component implements XIntrospection. The method XIntrospection::inspect(any object) + returns an XIntrospectionAccess that provides information about the methods, properties + and listeners supported by the inspected object. Matching pairs of getName/setName() + methods will also be offered as property "Name". +</description> + <loader-name> com.sun.star.loader.SharedLibrary </loader-name> + <language> c++ </language> + <status value="final"/> + <supported-service> com.sun.star.beans.Introspection </supported-service> + <service-dependency> com.sun.star.reflection.CoreReflection </service-dependency> + <type>com.sun.star.lang.DisposedException</type> + <type> com.sun.star.beans.XIntrospection </type> + <type> com.sun.star.beans.XIntrospectionAccess </type> + <type> com.sun.star.beans.XPropertySet </type> + <type> com.sun.star.beans.XFastPropertySet </type> + <type> com.sun.star.beans.XMaterialHolder </type> + <type> com.sun.star.beans.XExactName </type> + <type> com.sun.star.beans.PropertyAttribute </type> + <type> com.sun.star.beans.PropertyConcept </type> + <type> com.sun.star.beans.MethodConcept </type> + <type> com.sun.star.lang.XEventListener </type> + <type> com.sun.star.lang.XInitialization </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XSingleComponentFactory </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.uno.TypeClass </type> + <type> com.sun.star.uno.DeploymentException </type> + <type> com.sun.star.uno.XComponentContext </type> + <type> com.sun.star.container.XEnumerationAccess </type> + <type> com.sun.star.container.XNameContainer </type> + <type> com.sun.star.container.XIndexContainer </type> + <type> com.sun.star.reflection.XIdlReflection </type> + <type> com.sun.star.reflection.XIdlClassProvider </type> + <type> com.sun.star.reflection.XIdlClass </type> + <type> com.sun.star.reflection.XIdlField2 </type> + <type> com.sun.star.reflection.XIdlArray </type> + <type> com.sun.star.reflection.FieldAccessMode </type> + </component-description> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> sal </project-build-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> sal3 </runtime-module-dependency> +</module-description> diff --git a/stoc/source/inspect/introspection.component b/stoc/source/inspect/introspection.component new file mode 100644 index 000000000000..349fb0c9dfbe --- /dev/null +++ b/stoc/source/inspect/introspection.component @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.stoc.Introspection"> + <service name="com.sun.star.beans.Introspection"/> + </implementation> +</component> diff --git a/stoc/source/inspect/introspection.cxx b/stoc/source/inspect/introspection.cxx new file mode 100644 index 000000000000..051ff3e2ae3c --- /dev/null +++ b/stoc/source/inspect/introspection.cxx @@ -0,0 +1,3091 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include <string.h> + +// Schalter fuer Introspection-Caching +#ifndef OS2 +#define USE_INTROSPECTION_CACHE +#endif + +#ifdef USE_INTROSPECTION_CACHE +#define INTROSPECTION_CACHE_MAX_SIZE 100 +#endif +#include <osl/diagnose.h> +#include <osl/mutex.hxx> +#include <osl/thread.h> +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/weak.hxx> +#include <cppuhelper/component.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/implbase3.hxx> +#include <cppuhelper/typeprovider.hxx> + +#include <com/sun/star/uno/DeploymentException.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XEventListener.hpp> +#include <com/sun/star/reflection/XIdlReflection.hpp> +#include <com/sun/star/reflection/XIdlClassProvider.hpp> +#include <com/sun/star/reflection/XIdlClass.hpp> +#include <com/sun/star/reflection/XIdlField2.hpp> +#include <com/sun/star/beans/UnknownPropertyException.hpp> +#include <com/sun/star/beans/Property.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/XFastPropertySet.hpp> +#include <com/sun/star/beans/XIntrospection.hpp> +#include <com/sun/star/beans/XIntrospectionAccess.hpp> +#include <com/sun/star/beans/XMaterialHolder.hpp> +#include <com/sun/star/beans/XExactName.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyConcept.hpp> +#include <com/sun/star/beans/MethodConcept.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/container/XIndexContainer.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> + +#include <rtl/ustrbuf.hxx> +#include <rtl/strbuf.hxx> +#include <hash_map> + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::reflection; +using namespace com::sun::star::container; +using namespace com::sun::star::registry; +using namespace com::sun::star::beans; +using namespace com::sun::star::beans::PropertyAttribute; +using namespace com::sun::star::beans::PropertyConcept; +using namespace com::sun::star::beans::MethodConcept; +using namespace cppu; +using namespace osl; +using namespace rtl; + +#define IMPLEMENTATION_NAME "com.sun.star.comp.stoc.Introspection" +#define SERVICE_NAME "com.sun.star.beans.Introspection" + +namespace stoc_inspect +{ + +typedef WeakImplHelper3< XIntrospectionAccess, XMaterialHolder, XExactName > IntrospectionAccessHelper; + + +//================================================================================================== + +// Spezial-Wert fuer Method-Concept, um "normale" Funktionen kennzeichnen zu koennen +#define MethodConcept_NORMAL_IMPL 0x80000000 + + +// Methode zur Feststellung, ob eine Klasse von einer anderen abgeleitet ist +sal_Bool isDerivedFrom( Reference<XIdlClass> xToTestClass, Reference<XIdlClass> xDerivedFromClass ) +{ + Sequence< Reference<XIdlClass> > aClassesSeq = xToTestClass->getSuperclasses(); + const Reference<XIdlClass>* pClassesArray = aClassesSeq.getConstArray(); + sal_Int32 nSuperClassCount = aClassesSeq.getLength(); + sal_Int32 i; + for( i = 0 ; i < nSuperClassCount ; i++ ) + { + const Reference<XIdlClass>& rxClass = pClassesArray[i]; + if( xDerivedFromClass->equals( rxClass ) ) + { + // Treffer + return sal_True; + } + else + { + // Rekursiv weitersuchen + return isDerivedFrom( rxClass, xDerivedFromClass ); + } + } + return sal_False; +} + +//======================================================================== + +// *** Klassifizierung der Properties (kein enum, um Sequence verwenden zu koennen) *** +// Properties aus einem PropertySet-Interface +#define MAP_PROPERTY_SET 0 +// Properties aus Fields +#define MAP_FIELD 1 +// Properties, die durch get/set-Methoden beschrieben werden +#define MAP_GETSET 2 +// Properties, die nur eine set-Methode haben +#define MAP_SETONLY 3 + + +// Schrittweite, in der die Groesse der Sequences angepasst wird +#define ARRAY_SIZE_STEP 20 + + + +//************************************** +//*** IntrospectionAccessStatic_Impl *** +//************************************** +// Entspricht dem alten IntrospectionAccessImpl, bildet jetzt den statischen +// Anteil des neuen Instanz-bezogenen ImplIntrospectionAccess + +// ACHTUNG !!! Von Hand refcounten !!! + + +// Hashtable fuer die Suche nach Namen +struct hashName_Impl +{ + size_t operator()(const OUString Str) const + { + return (size_t)Str.hashCode(); + } +}; + +struct eqName_Impl +{ + sal_Bool operator()(const OUString Str1, const OUString Str2) const + { + return ( Str1 == Str2 ); + } +}; + +typedef std::hash_map +< + OUString, + sal_Int32, + hashName_Impl, + eqName_Impl +> +IntrospectionNameMap; + + +// Hashtable zur Zuordnung der exakten Namen zu den zu Lower-Case +// konvertierten Namen, dient zur Unterst�tzung von XExactName +typedef std::hash_map +< + OUString, + OUString, + hashName_Impl, + eqName_Impl +> +LowerToExactNameMap; + + +class ImplIntrospectionAccess; +class IntrospectionAccessStatic_Impl +{ + friend class ImplIntrospection; + friend class ImplIntrospectionAccess; + + // CoreReflection halten + Reference< XIdlReflection > mxCoreReflection; + + // InterfaceSequences, um Zusatz-Infos zu einer Property speichern zu koennen. + // z.B. das Field bei MAP_FIELD, die get/set-Methoden bei MAP_GETSET usw. + Sequence< Reference<XInterface> > aInterfaceSeq1; + Sequence< Reference<XInterface> > aInterfaceSeq2; + + // Hashtables fuer die Namen + IntrospectionNameMap maPropertyNameMap; + IntrospectionNameMap maMethodNameMap; + LowerToExactNameMap maLowerToExactNameMap; + + // Sequence aller Properties, auch zum Liefern aus getProperties() + Sequence<Property> maAllPropertySeq; + + // Mapping der Properties auf Zugriffs-Arten + Sequence<sal_Int16> maMapTypeSeq; + + // Klassifizierung der gefundenen Methoden + Sequence<sal_Int32> maPropertyConceptSeq; + + // Anzahl der Properties + sal_Int32 mnPropCount; + + // Anzahl der Properties, die den jeweiligen Konzepten zugeordnet sind + //sal_Int32 mnDangerousPropCount; + sal_Int32 mnPropertySetPropCount; + sal_Int32 mnAttributePropCount; + sal_Int32 mnMethodPropCount; + + // Flag, ob ein FastPropertySet unterstuetzt wird + sal_Bool mbFastPropSet; + + // Original-Handles eines FastPropertySets + sal_Int32* mpOrgPropertyHandleArray; + + // MethodSequence, die alle Methoden aufnimmt + Sequence< Reference<XIdlMethod> > maAllMethodSeq; + + // Klassifizierung der gefundenen Methoden + Sequence<sal_Int32> maMethodConceptSeq; + + // Anzahl der Methoden + sal_Int32 mnMethCount; + + // Sequence der Listener, die angemeldet werden koennen + Sequence< Type > maSupportedListenerSeq; + + // BaseInit (soll spaeter in der Applikation erfolgen!) + void BaseInit( void ); + + // Hilfs-Methoden zur Groessen-Anpassung der Sequences + void checkPropertyArraysSize + ( + Property*& rpAllPropArray, + sal_Int16*& rpMapTypeArray, + sal_Int32*& rpPropertyConceptArray, + sal_Int32 iNextIndex + ); + void checkInterfaceArraySize( Sequence< Reference<XInterface> >& rSeq, Reference<XInterface>*& rpInterfaceArray, + sal_Int32 iNextIndex ); + + // RefCount + sal_Int32 nRefCount; + + +public: + IntrospectionAccessStatic_Impl( Reference< XIdlReflection > xCoreReflection_ ); + ~IntrospectionAccessStatic_Impl() + { + delete[] mpOrgPropertyHandleArray; + } + sal_Int32 getPropertyIndex( const OUString& aPropertyName ) const; + sal_Int32 getMethodIndex( const OUString& aMethodName ) const; + + void acquire() { nRefCount++; } + void release() + { + nRefCount--; + if( nRefCount <= 0 ) + delete this; + } + + // Methoden von XIntrospectionAccess (ALT, jetzt nur Impl) + void setPropertyValue(const Any& obj, const OUString& aPropertyName, const Any& aValue) const; +// void setPropertyValue(Any& obj, const OUString& aPropertyName, const Any& aValue) const; + Any getPropertyValue(const Any& obj, const OUString& aPropertyName) const; + void setPropertyValueByIndex(const Any& obj, sal_Int32 nIndex, const Any& aValue) const; +// void setPropertyValueByIndex(Any& obj, sal_Int32 nIndex, const Any& aValue) const; + Any getPropertyValueByIndex(const Any& obj, sal_Int32 nIndex) const; + + Sequence<Property> getProperties(void) const { return maAllPropertySeq; } + Sequence< Reference<XIdlMethod> > getMethods(void) const { return maAllMethodSeq; } + Sequence< Type > getSupportedListeners(void) const { return maSupportedListenerSeq; } + Sequence<sal_Int32> getPropertyConcepts(void) const { return maPropertyConceptSeq; } + Sequence<sal_Int32> getMethodConcepts(void) const { return maMethodConceptSeq; } +}; + + +// Ctor +IntrospectionAccessStatic_Impl::IntrospectionAccessStatic_Impl( Reference< XIdlReflection > xCoreReflection_ ) + : mxCoreReflection( xCoreReflection_ ) +{ + aInterfaceSeq1.realloc( ARRAY_SIZE_STEP ); + aInterfaceSeq2.realloc( ARRAY_SIZE_STEP ); + + // Property-Daten + maAllPropertySeq.realloc( ARRAY_SIZE_STEP ); + maMapTypeSeq.realloc( ARRAY_SIZE_STEP ); + maPropertyConceptSeq.realloc( ARRAY_SIZE_STEP ); + + mbFastPropSet = sal_False; + mpOrgPropertyHandleArray = NULL; + + mnPropCount = 0; + //mnDangerousPropCount = 0; + mnPropertySetPropCount = 0; + mnAttributePropCount = 0; + mnMethodPropCount = 0; + + // Method-Daten + mnMethCount = 0; + + // Eigenens RefCounting + nRefCount = 0; +} + +// Von Hand refcounten !!! + + +sal_Int32 IntrospectionAccessStatic_Impl::getPropertyIndex( const OUString& aPropertyName ) const +{ + sal_Int32 iHashResult = -1; + IntrospectionAccessStatic_Impl* pThis = (IntrospectionAccessStatic_Impl*)this; + IntrospectionNameMap::iterator aIt = pThis->maPropertyNameMap.find( aPropertyName ); + if( !( aIt == pThis->maPropertyNameMap.end() ) ) + iHashResult = (*aIt).second; + return iHashResult; +} + +sal_Int32 IntrospectionAccessStatic_Impl::getMethodIndex( const OUString& aMethodName ) const +{ + sal_Int32 iHashResult = -1; + IntrospectionAccessStatic_Impl* pThis = (IntrospectionAccessStatic_Impl*)this; + IntrospectionNameMap::iterator aIt = pThis->maMethodNameMap.find( aMethodName ); + if( !( aIt == pThis->maMethodNameMap.end() ) ) + { + iHashResult = (*aIt).second; + } + // #95159 Check if full qualified name matches + else + { + sal_Int32 nSearchFrom = aMethodName.getLength(); + nSearchFrom = aMethodName.getLength(); + while( true ) + { + // Strategy: Search back until the first '_' is found + sal_Int32 nFound = aMethodName.lastIndexOf( '_', nSearchFrom ); + if( nFound == -1 ) + break; + + OUString aPureMethodName = aMethodName.copy( nFound + 1 ); + + aIt = pThis->maMethodNameMap.find( aPureMethodName ); + if( !( aIt == pThis->maMethodNameMap.end() ) ) + { + // Check if it can be a type? + // Problem: Does not work if package names contain _ ?! + OUString aStr = aMethodName.copy( 0, nFound ); + OUString aTypeName = aStr.replace( '_', '.' ); + Reference< XIdlClass > xClass = mxCoreReflection->forName( aTypeName ); + if( xClass.is() ) + { + // If this is a valid class it could be the right method + + // Could be the right method, type has to be checked + iHashResult = (*aIt).second; + + const Reference<XIdlMethod>* pMethods = maAllMethodSeq.getConstArray(); + const Reference<XIdlMethod> xMethod = pMethods[ iHashResult ]; + + Reference< XIdlClass > xMethClass = xMethod->getDeclaringClass(); + if( xClass->equals( xMethClass ) ) + { + break; + } + else + { + iHashResult = -1; + + // Could also be another method with the same name + // Iterate over all methods + sal_Int32 nLen = maAllMethodSeq.getLength(); + for( int i = 0 ; i < nLen ; ++i ) + { + const Reference<XIdlMethod> xMethod2 = pMethods[ i ]; + + OUString aTestClassName = xMethod2->getDeclaringClass()->getName(); + OUString aTestMethodName = xMethod2->getName(); + + if( xMethod2->getName() == aPureMethodName ) + { + Reference< XIdlClass > xMethClass2 = xMethod2->getDeclaringClass(); + + if( xClass->equals( xMethClass2 ) ) + { + iHashResult = i; + break; + } + } + } + + if( iHashResult != -1 ) + break; + } + } + } + + nSearchFrom = nFound - 1; + if( nSearchFrom < 0 ) + break; + } + } + return iHashResult; +} + +void IntrospectionAccessStatic_Impl::setPropertyValue( const Any& obj, const OUString& aPropertyName, const Any& aValue ) const +//void IntrospectionAccessStatic_Impl::setPropertyValue( Any& obj, const OUString& aPropertyName, const Any& aValue ) const +{ + sal_Int32 i = getPropertyIndex( aPropertyName ); + if( i != -1 ) + setPropertyValueByIndex( obj, (sal_Int32)i, aValue ); + else + throw UnknownPropertyException(); +} + +void IntrospectionAccessStatic_Impl::setPropertyValueByIndex(const Any& obj, sal_Int32 nSequenceIndex, const Any& aValue) const +//void IntrospectionAccessStatic_Impl::setPropertyValueByIndex( Any& obj, sal_Int32 nSequenceIndex, const Any& aValue) const +{ + // Handelt es sich bei dem uebergebenen Objekt ueberhaupt um was passendes? + TypeClass eObjType = obj.getValueType().getTypeClass(); + + Reference<XInterface> xInterface; + if( eObjType == TypeClass_INTERFACE ) + { + xInterface = *( Reference<XInterface>*)obj.getValue(); + } + else if( nSequenceIndex >= mnPropCount || ( eObjType != TypeClass_STRUCT && eObjType != TypeClass_EXCEPTION ) ) + { + throw IllegalArgumentException(); + } + + // Flags pruefen + const Property* pProps = maAllPropertySeq.getConstArray(); + if( (pProps[ nSequenceIndex ].Attributes & READONLY) != 0 ) + { + throw UnknownPropertyException(); + } + + const sal_Int16* pMapTypeArray = maMapTypeSeq.getConstArray(); + switch( pMapTypeArray[ nSequenceIndex ] ) + { + case MAP_PROPERTY_SET: + { + // Property besorgen + const Property& rProp = maAllPropertySeq.getConstArray()[ nSequenceIndex ]; + + // Interface-Parameter auf den richtigen Typ bringen + sal_Bool bUseCopy = sal_False; + Any aRealValue; + + TypeClass eValType = aValue.getValueType().getTypeClass(); + if( eValType == TypeClass_INTERFACE ) + { + Type aPropType = rProp.Type; + OUString aTypeName( aPropType.getTypeName() ); + Reference< XIdlClass > xPropClass = mxCoreReflection->forName( aTypeName ); + //Reference<XIdlClass> xPropClass = rProp.Type; + if( xPropClass.is() && xPropClass->getTypeClass() == TypeClass_INTERFACE ) + { + Reference<XInterface> valInterface = *(Reference<XInterface>*)aValue.getValue(); + if( valInterface.is() ) + { + //Any queryInterface( const Type& rType ); + aRealValue = valInterface->queryInterface( aPropType ); + if( aRealValue.hasValue() ) + bUseCopy = sal_True; + } + } + } + + // Haben wir ein FastPropertySet und ein gueltiges Handle? + // ACHTUNG: An dieser Stelle wird ausgenutzt, dass das PropertySet + // zu Beginn des Introspection-Vorgangs abgefragt wird. + sal_Int32 nOrgHandle; + if( mbFastPropSet && ( nOrgHandle = mpOrgPropertyHandleArray[ nSequenceIndex ] ) != -1 ) + { + // PropertySet-Interface holen + Reference<XFastPropertySet> xFastPropSet = + Reference<XFastPropertySet>::query( xInterface ); + if( xFastPropSet.is() ) + { + xFastPropSet->setFastPropertyValue( nOrgHandle, bUseCopy ? aRealValue : aValue ); + } + else + { + // throw UnknownPropertyException + } + } + // sonst eben das normale nehmen + else + { + // PropertySet-Interface holen + Reference<XPropertySet> xPropSet = + Reference<XPropertySet>::query( xInterface ); + if( xPropSet.is() ) + { + xPropSet->setPropertyValue( rProp.Name, bUseCopy ? aRealValue : aValue ); + } + else + { + // throw UnknownPropertyException + } + } + } + break; + + case MAP_FIELD: + { + Reference<XIdlField> xField = (XIdlField*)(aInterfaceSeq1.getConstArray()[ nSequenceIndex ].get()); + Reference<XIdlField2> xField2(xField, UNO_QUERY); + if( xField2.is() ) + { + xField2->set( (Any&)obj, aValue ); + // IllegalArgumentException + // NullPointerException + } else + if( xField.is() ) + { + xField->set( obj, aValue ); + // IllegalArgumentException + // NullPointerException + } + else + { + // throw IllegalArgumentException(); + } + } + break; + + case MAP_GETSET: + case MAP_SETONLY: + { + // set-Methode holen + Reference<XIdlMethod> xMethod = (XIdlMethod*)(aInterfaceSeq2.getConstArray()[ nSequenceIndex ].get()); + if( xMethod.is() ) + { + Sequence<Any> args( 1 ); + args.getArray()[0] = aValue; + xMethod->invoke( obj, args ); + } + else + { + // throw IllegalArgumentException(); + } + } + break; + } +} + +Any IntrospectionAccessStatic_Impl::getPropertyValue( const Any& obj, const OUString& aPropertyName ) const +{ + sal_Int32 i = getPropertyIndex( aPropertyName ); + if( i != -1 ) + return getPropertyValueByIndex( obj, i ); + + throw UnknownPropertyException(); +} + +Any IntrospectionAccessStatic_Impl::getPropertyValueByIndex(const Any& obj, sal_Int32 nSequenceIndex) const +{ + Any aRet; + + // Handelt es sich bei dem uebergebenen Objekt ueberhaupt um was passendes? + TypeClass eObjType = obj.getValueType().getTypeClass(); + + Reference<XInterface> xInterface; + if( eObjType == TypeClass_INTERFACE ) + { + xInterface = *(Reference<XInterface>*)obj.getValue(); + } + else if( nSequenceIndex >= mnPropCount || ( eObjType != TypeClass_STRUCT && eObjType != TypeClass_EXCEPTION ) ) + { + // throw IllegalArgumentException(); + return aRet; + } + + const sal_Int16* pMapTypeArray = maMapTypeSeq.getConstArray(); + switch( pMapTypeArray[ nSequenceIndex ] ) + { + case MAP_PROPERTY_SET: + { + // Property besorgen + const Property& rProp = maAllPropertySeq.getConstArray()[ nSequenceIndex ]; + + // Haben wir ein FastPropertySet und ein gueltiges Handle? + // ACHTUNG: An dieser Stelle wird ausgenutzt, dass das PropertySet + // zu Beginn des Introspection-Vorgangs abgefragt wird. + sal_Int32 nOrgHandle; + if( mbFastPropSet && ( nOrgHandle = mpOrgPropertyHandleArray[ nSequenceIndex ] ) != -1 ) + { + // PropertySet-Interface holen + Reference<XFastPropertySet> xFastPropSet = + Reference<XFastPropertySet>::query( xInterface ); + if( xFastPropSet.is() ) + { + aRet = xFastPropSet->getFastPropertyValue( nOrgHandle); + } + else + { + // throw UnknownPropertyException + return aRet; + } + } + // sonst eben das normale nehmen + else + { + // PropertySet-Interface holen + Reference<XPropertySet> xPropSet = + Reference<XPropertySet>::query( xInterface ); + if( xPropSet.is() ) + { + aRet = xPropSet->getPropertyValue( rProp.Name ); + } + else + { + // throw UnknownPropertyException + return aRet; + } + } + } + break; + + case MAP_FIELD: + { + Reference<XIdlField> xField = (XIdlField*)(aInterfaceSeq1.getConstArray()[ nSequenceIndex ].get()); + if( xField.is() ) + { + aRet = xField->get( obj ); + // IllegalArgumentException + // NullPointerException + } + else + { + // throw IllegalArgumentException(); + return aRet; + } + } + break; + + case MAP_GETSET: + { + // get-Methode holen + Reference<XIdlMethod> xMethod = (XIdlMethod*)(aInterfaceSeq1.getConstArray()[ nSequenceIndex ].get()); + if( xMethod.is() ) + { + Sequence<Any> args; + aRet = xMethod->invoke( obj, args ); + } + else + { + // throw IllegalArgumentException(); + return aRet; + } + } + break; + + case MAP_SETONLY: + // get-Methode gibt es nicht + // throw WriteOnlyPropertyException(); + return aRet; + } + return aRet; +} + + +// Hilfs-Methoden zur Groessen-Anpassung der Sequences +void IntrospectionAccessStatic_Impl::checkPropertyArraysSize +( + Property*& rpAllPropArray, + sal_Int16*& rpMapTypeArray, + sal_Int32*& rpPropertyConceptArray, + sal_Int32 iNextIndex +) +{ + sal_Int32 nLen = maAllPropertySeq.getLength(); + if( iNextIndex >= nLen ) + { + maAllPropertySeq.realloc( nLen + ARRAY_SIZE_STEP ); + rpAllPropArray = maAllPropertySeq.getArray(); + + maMapTypeSeq.realloc( nLen + ARRAY_SIZE_STEP ); + rpMapTypeArray = maMapTypeSeq.getArray(); + + maPropertyConceptSeq.realloc( nLen + ARRAY_SIZE_STEP ); + rpPropertyConceptArray = maPropertyConceptSeq.getArray(); + } +} + +void IntrospectionAccessStatic_Impl::checkInterfaceArraySize( Sequence< Reference<XInterface> >& rSeq, + Reference<XInterface>*& rpInterfaceArray, sal_Int32 iNextIndex ) +{ + sal_Int32 nLen = rSeq.getLength(); + if( iNextIndex >= nLen ) + { + // Neue Groesse mit ARRAY_SIZE_STEP abgleichen + sal_Int32 nMissingSize = iNextIndex - nLen + 1; + sal_Int32 nSteps = nMissingSize / ARRAY_SIZE_STEP + 1; + sal_Int32 nNewSize = nLen + nSteps * ARRAY_SIZE_STEP; + + rSeq.realloc( nNewSize ); + rpInterfaceArray = rSeq.getArray(); + } +} + + +//******************************* +//*** ImplIntrospectionAdapter *** +//******************************* + +// Neue Impl-Klasse im Rahmen der Introspection-Umstellung auf Instanz-gebundene +// Introspection mit Property-Zugriff ueber XPropertySet. Die alte Klasse +// ImplIntrospectionAccess lebt als IntrospectionAccessStatic_Impl +class ImplIntrospectionAdapter : + public XPropertySet, public XFastPropertySet, public XPropertySetInfo, + public XNameContainer, public XIndexContainer, + public XEnumerationAccess, public XIdlArray, + public OWeakObject +{ + // Parent-Objekt + ImplIntrospectionAccess* mpAccess; + + // Untersuchtes Objekt + const Any& mrInspectedObject; + + // Statische Daten der Introspection + IntrospectionAccessStatic_Impl* mpStaticImpl; + + // Objekt als Interface + Reference<XInterface> mxIface; + + // Original-Interfaces des Objekts + Reference<XElementAccess> mxObjElementAccess; + Reference<XNameContainer> mxObjNameContainer; + Reference<XNameAccess> mxObjNameAccess; + Reference<XIndexAccess> mxObjIndexAccess; + Reference<XIndexContainer> mxObjIndexContainer; + Reference<XEnumerationAccess> mxObjEnumerationAccess; + Reference<XIdlArray> mxObjIdlArray; + +public: + ImplIntrospectionAdapter( ImplIntrospectionAccess* pAccess_, + const Any& obj, IntrospectionAccessStatic_Impl* pStaticImpl_ ); + ~ImplIntrospectionAdapter(); + + // Methoden von XInterface + virtual Any SAL_CALL queryInterface( const Type& rType ) throw( RuntimeException ); + virtual void SAL_CALL acquire() throw() { OWeakObject::acquire(); } + virtual void SAL_CALL release() throw() { OWeakObject::release(); } + + // Methoden von XPropertySet + virtual Reference<XPropertySetInfo> SAL_CALL getPropertySetInfo() throw( RuntimeException ); + virtual void SAL_CALL setPropertyValue(const OUString& aPropertyName, const Any& aValue) + throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException ); + virtual Any SAL_CALL getPropertyValue(const OUString& aPropertyName) + throw( UnknownPropertyException, WrappedTargetException, RuntimeException ); + virtual void SAL_CALL addPropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener) + throw( UnknownPropertyException, WrappedTargetException, RuntimeException ); + virtual void SAL_CALL removePropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener) + throw( UnknownPropertyException, WrappedTargetException, RuntimeException ); + virtual void SAL_CALL addVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener) + throw( UnknownPropertyException, WrappedTargetException, RuntimeException ); + virtual void SAL_CALL removeVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener) + throw( UnknownPropertyException, WrappedTargetException, RuntimeException ); + + // Methoden von XFastPropertySet + virtual void SAL_CALL setFastPropertyValue(sal_Int32 nHandle, const Any& aValue) + throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException ); + virtual Any SAL_CALL getFastPropertyValue(sal_Int32 nHandle) + throw( UnknownPropertyException, WrappedTargetException, RuntimeException ); + + // Methoden von XPropertySetInfo + virtual Sequence< Property > SAL_CALL getProperties(void) throw( RuntimeException ); + virtual Property SAL_CALL getPropertyByName(const OUString& Name) throw( RuntimeException ); + virtual sal_Bool SAL_CALL hasPropertyByName(const OUString& Name) throw( RuntimeException ); + + // Methoden von XElementAccess + virtual Type SAL_CALL getElementType(void) throw( RuntimeException ); + virtual sal_Bool SAL_CALL hasElements(void) throw( RuntimeException ); + + // Methoden von XNameAccess + virtual Any SAL_CALL getByName(const OUString& Name) + throw( NoSuchElementException, WrappedTargetException, RuntimeException ); + virtual Sequence<OUString> SAL_CALL getElementNames(void) throw( RuntimeException ); + virtual sal_Bool SAL_CALL hasByName(const OUString& Name) throw( RuntimeException ); + + // Methoden von XNameContainer + virtual void SAL_CALL insertByName(const OUString& Name, const Any& Element) + throw( IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException ); + virtual void SAL_CALL replaceByName(const OUString& Name, const Any& Element) + throw( IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException ); + virtual void SAL_CALL removeByName(const OUString& Name) + throw( NoSuchElementException, WrappedTargetException, RuntimeException ); + + // Methoden von XIndexAccess + virtual sal_Int32 SAL_CALL getCount(void) throw( RuntimeException ); + virtual Any SAL_CALL getByIndex(sal_Int32 Index) + throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ); + + // Methoden von XIndexContainer + virtual void SAL_CALL insertByIndex(sal_Int32 Index, const Any& Element) + throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException ); + virtual void SAL_CALL replaceByIndex(sal_Int32 Index, const Any& Element) + throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException ); + virtual void SAL_CALL removeByIndex(sal_Int32 Index) + throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ); + + // Methoden von XEnumerationAccess + virtual Reference<XEnumeration> SAL_CALL createEnumeration(void) throw( RuntimeException ); + + // Methoden von XIdlArray + virtual void SAL_CALL realloc(Any& array, sal_Int32 length) + throw( IllegalArgumentException, RuntimeException ); + virtual sal_Int32 SAL_CALL getLen(const Any& array) throw( IllegalArgumentException, RuntimeException ); + virtual Any SAL_CALL get(const Any& array, sal_Int32 index) + throw( IllegalArgumentException, ArrayIndexOutOfBoundsException, RuntimeException ); + virtual void SAL_CALL set(Any& array, sal_Int32 index, const Any& value) + throw( IllegalArgumentException, ArrayIndexOutOfBoundsException, RuntimeException ); +}; + +ImplIntrospectionAdapter::ImplIntrospectionAdapter( ImplIntrospectionAccess* pAccess_, + const Any& obj, IntrospectionAccessStatic_Impl* pStaticImpl_ ) + : mpAccess( pAccess_), mrInspectedObject( obj ), mpStaticImpl( pStaticImpl_ ) +{ + mpStaticImpl->acquire(); + + // Objekt als Interfaceholen + TypeClass eType = mrInspectedObject.getValueType().getTypeClass(); + if( eType == TypeClass_INTERFACE ) + { + mxIface = *( Reference< XInterface >*)mrInspectedObject.getValue(); + + mxObjElementAccess = Reference<XElementAccess>::query( mxIface ); + mxObjNameAccess = Reference<XNameAccess>::query( mxIface ); + mxObjNameContainer = Reference<XNameContainer>::query( mxIface ); + mxObjIndexAccess = Reference<XIndexAccess>::query( mxIface ); + mxObjIndexContainer = Reference<XIndexContainer>::query( mxIface ); + mxObjEnumerationAccess = Reference<XEnumerationAccess>::query( mxIface ); + mxObjIdlArray = Reference<XIdlArray>::query( mxIface ); + } +} + +ImplIntrospectionAdapter::~ImplIntrospectionAdapter() +{ + mpStaticImpl->release(); +} + +// Methoden von XInterface +Any SAL_CALL ImplIntrospectionAdapter::queryInterface( const Type& rType ) + throw( RuntimeException ) +{ + Any aRet( ::cppu::queryInterface( + rType, + static_cast< XPropertySet * >( this ), + static_cast< XFastPropertySet * >( this ), + static_cast< XPropertySetInfo * >( this ) ) ); + if( !aRet.hasValue() ) + aRet = OWeakObject::queryInterface( rType ); + + if( !aRet.hasValue() ) + { + // Wrapper fuer die Objekt-Interfaces + if( ( mxObjElementAccess.is() && (aRet = ::cppu::queryInterface + ( rType, static_cast< XElementAccess* >( static_cast< XNameAccess* >( this ) ) ) ).hasValue() ) + || ( mxObjNameAccess.is() && (aRet = ::cppu::queryInterface( rType, static_cast< XNameAccess* >( this ) ) ).hasValue() ) + || ( mxObjNameContainer.is() && (aRet = ::cppu::queryInterface( rType, static_cast< XNameContainer* >( this ) ) ).hasValue() ) + || ( mxObjIndexAccess.is() && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexAccess* >( this ) ) ).hasValue() ) + || ( mxObjIndexContainer.is() && (aRet = ::cppu::queryInterface( rType, static_cast< XIndexContainer* >( this ) ) ).hasValue() ) + || ( mxObjEnumerationAccess .is() && (aRet = ::cppu::queryInterface( rType, static_cast< XEnumerationAccess* >( this ) ) ).hasValue() ) + || ( mxObjIdlArray.is() && (aRet = ::cppu::queryInterface( rType, static_cast< XIdlArray* >( this ) ) ).hasValue() ) + ) + { + } + } + return aRet; +} + + +//******************************* +//*** ImplIntrospectionAccess *** +//******************************* + +// Neue Impl-Klasse im Rahmen der Introspection-Umstellung auf Instanz-gebundene +// Introspection mit Property-Zugriff ueber XPropertySet. Die alte Klasse +// ImplIntrospectionAccess lebt als IntrospectionAccessStatic_Impl +class ImplIntrospectionAccess : IntrospectionAccessHelper +{ + friend class ImplIntrospection; + + // Untersuchtes Objekt + Any maInspectedObject; + + // Als Interface + Reference<XInterface> mxIface; + + // Statische Daten der Introspection + IntrospectionAccessStatic_Impl* mpStaticImpl; + + // Adapter-Implementation + ImplIntrospectionAdapter* mpAdapter; + + // Letzte Sequence, die bei getProperties geliefert wurde (Optimierung) + Sequence<Property> maLastPropertySeq; + sal_Int32 mnLastPropertyConcept; + + // Letzte Sequence, die bei getMethods geliefert wurde (Optimierung) + Sequence<Reference<XIdlMethod> > maLastMethodSeq; + sal_Int32 mnLastMethodConcept; + +public: + ImplIntrospectionAccess( const Any& obj, IntrospectionAccessStatic_Impl* pStaticImpl_ ); + ~ImplIntrospectionAccess(); + + // Methoden von XIntrospectionAccess + virtual sal_Int32 SAL_CALL getSuppliedMethodConcepts(void) + throw( RuntimeException ); + virtual sal_Int32 SAL_CALL getSuppliedPropertyConcepts(void) + throw( RuntimeException ); + virtual Property SAL_CALL getProperty(const OUString& Name, sal_Int32 PropertyConcepts) + throw( NoSuchElementException, RuntimeException ); + virtual sal_Bool SAL_CALL hasProperty(const OUString& Name, sal_Int32 PropertyConcepts) + throw( RuntimeException ); + virtual Sequence< Property > SAL_CALL getProperties(sal_Int32 PropertyConcepts) + throw( RuntimeException ); + virtual Reference<XIdlMethod> SAL_CALL getMethod(const OUString& Name, sal_Int32 MethodConcepts) + throw( NoSuchMethodException, RuntimeException ); + virtual sal_Bool SAL_CALL hasMethod(const OUString& Name, sal_Int32 MethodConcepts) + throw( RuntimeException ); + virtual Sequence< Reference<XIdlMethod> > SAL_CALL getMethods(sal_Int32 MethodConcepts) + throw( RuntimeException ); + virtual Sequence< Type > SAL_CALL getSupportedListeners(void) + throw( RuntimeException ); + using OWeakObject::queryAdapter; + virtual Reference<XInterface> SAL_CALL queryAdapter( const Type& rType ) + throw( IllegalTypeException, RuntimeException ); + + // Methoden von XMaterialHolder + virtual Any SAL_CALL getMaterial(void) throw(RuntimeException); + + // Methoden von XExactName + virtual OUString SAL_CALL getExactName( const OUString& rApproximateName ) throw( RuntimeException ); +}; + +ImplIntrospectionAccess::ImplIntrospectionAccess + ( const Any& obj, IntrospectionAccessStatic_Impl* pStaticImpl_ ) + : maInspectedObject( obj ), mpStaticImpl( pStaticImpl_ ), mpAdapter( NULL ) +{ + mpStaticImpl->acquire(); + + // Objekt als Interface merken, wenn moeglich + TypeClass eType = maInspectedObject.getValueType().getTypeClass(); + if( eType == TypeClass_INTERFACE ) + mxIface = *(Reference<XInterface>*)maInspectedObject.getValue(); + + mnLastPropertyConcept = -1; + mnLastMethodConcept = -1; +} + +ImplIntrospectionAccess::~ImplIntrospectionAccess() +{ + mpStaticImpl->release(); + + // Eigene Referenz loslassen + if (mpAdapter) + mpAdapter->release(); +} + + +//*************************************************** +//*** Implementation von ImplIntrospectionAdapter *** +//*************************************************** + +// Methoden von XPropertySet +Reference<XPropertySetInfo> ImplIntrospectionAdapter::getPropertySetInfo(void) + throw( RuntimeException ) +{ + return (XPropertySetInfo *)this; +} + +void ImplIntrospectionAdapter::setPropertyValue(const OUString& aPropertyName, const Any& aValue) + throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException ) +{ + mpStaticImpl->setPropertyValue( mrInspectedObject, aPropertyName, aValue ); +} + +Any ImplIntrospectionAdapter::getPropertyValue(const OUString& aPropertyName) + throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) +{ + return mpStaticImpl->getPropertyValue( mrInspectedObject, aPropertyName ); +} + +void ImplIntrospectionAdapter::addPropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener) + throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) +{ + if( mxIface.is() ) + { + Reference<XPropertySet> xPropSet = + Reference<XPropertySet>::query( mxIface ); + //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY ); + if( xPropSet.is() ) + xPropSet->addPropertyChangeListener(aPropertyName, aListener); + } +} + +void ImplIntrospectionAdapter::removePropertyChangeListener(const OUString& aPropertyName, const Reference<XPropertyChangeListener>& aListener) + throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) +{ + if( mxIface.is() ) + { + Reference<XPropertySet> xPropSet = + Reference<XPropertySet>::query( mxIface ); + //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY ); + if( xPropSet.is() ) + xPropSet->removePropertyChangeListener(aPropertyName, aListener); + } +} + +void ImplIntrospectionAdapter::addVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener) + throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) +{ + if( mxIface.is() ) + { + Reference<XPropertySet> xPropSet = + Reference<XPropertySet>::query( mxIface ); + //Reference<XPropertySet> xPropSet( mxIface, USR_QUERY ); + if( xPropSet.is() ) + xPropSet->addVetoableChangeListener(aPropertyName, aListener); + } +} + +void ImplIntrospectionAdapter::removeVetoableChangeListener(const OUString& aPropertyName, const Reference<XVetoableChangeListener>& aListener) + throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) +{ + if( mxIface.is() ) + { + Reference<XPropertySet> xPropSet = + Reference<XPropertySet>::query( mxIface ); + if( xPropSet.is() ) + xPropSet->removeVetoableChangeListener(aPropertyName, aListener); + } +} + + +// Methoden von XFastPropertySet +void ImplIntrospectionAdapter::setFastPropertyValue(sal_Int32, const Any&) + throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException ) +{ +} + +Any ImplIntrospectionAdapter::getFastPropertyValue(sal_Int32) + throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) +{ + return Any(); +} + +// Methoden von XPropertySetInfo +Sequence< Property > ImplIntrospectionAdapter::getProperties(void) throw( RuntimeException ) +{ + return mpStaticImpl->getProperties(); +} + +Property ImplIntrospectionAdapter::getPropertyByName(const OUString& Name) + throw( RuntimeException ) +{ + return mpAccess->getProperty( Name, PropertyConcept::ALL ); +} + +sal_Bool ImplIntrospectionAdapter::hasPropertyByName(const OUString& Name) + throw( RuntimeException ) +{ + return mpAccess->hasProperty( Name, PropertyConcept::ALL ); +} + +// Methoden von XElementAccess +Type ImplIntrospectionAdapter::getElementType(void) throw( RuntimeException ) +{ + return mxObjElementAccess->getElementType(); +} + +sal_Bool ImplIntrospectionAdapter::hasElements(void) throw( RuntimeException ) +{ + return mxObjElementAccess->hasElements(); +} + +// Methoden von XNameAccess +Any ImplIntrospectionAdapter::getByName(const OUString& Name) + throw( NoSuchElementException, WrappedTargetException, RuntimeException ) +{ + return mxObjNameAccess->getByName( Name ); +} + +Sequence< OUString > ImplIntrospectionAdapter::getElementNames(void) + throw( RuntimeException ) +{ + return mxObjNameAccess->getElementNames(); +} + +sal_Bool ImplIntrospectionAdapter::hasByName(const OUString& Name) + throw( RuntimeException ) +{ + return mxObjNameAccess->hasByName( Name ); +} + +// Methoden von XNameContainer +void ImplIntrospectionAdapter::insertByName(const OUString& Name, const Any& Element) + throw( IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException ) +{ + mxObjNameContainer->insertByName( Name, Element ); +} + +void ImplIntrospectionAdapter::replaceByName(const OUString& Name, const Any& Element) + throw( IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException ) +{ + mxObjNameContainer->replaceByName( Name, Element ); +} + +void ImplIntrospectionAdapter::removeByName(const OUString& Name) + throw( NoSuchElementException, WrappedTargetException, RuntimeException ) +{ + mxObjNameContainer->removeByName( Name ); +} + +// Methoden von XIndexAccess +// Schon in XNameAccess: virtual Reference<XIdlClass> getElementType(void) const +sal_Int32 ImplIntrospectionAdapter::getCount(void) throw( RuntimeException ) +{ + return mxObjIndexAccess->getCount(); +} + +Any ImplIntrospectionAdapter::getByIndex(sal_Int32 Index) + throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + return mxObjIndexAccess->getByIndex( Index ); +} + +// Methoden von XIndexContainer +void ImplIntrospectionAdapter::insertByIndex(sal_Int32 Index, const Any& Element) + throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + mxObjIndexContainer->insertByIndex( Index, Element ); +} + +void ImplIntrospectionAdapter::replaceByIndex(sal_Int32 Index, const Any& Element) + throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + mxObjIndexContainer->replaceByIndex( Index, Element ); +} + +void ImplIntrospectionAdapter::removeByIndex(sal_Int32 Index) + throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) +{ + mxObjIndexContainer->removeByIndex( Index ); +} + +// Methoden von XEnumerationAccess +// Schon in XNameAccess: virtual Reference<XIdlClass> getElementType(void) const; +Reference<XEnumeration> ImplIntrospectionAdapter::createEnumeration(void) throw( RuntimeException ) +{ + return mxObjEnumerationAccess->createEnumeration(); +} + +// Methoden von XIdlArray +void ImplIntrospectionAdapter::realloc(Any& array, sal_Int32 length) + throw( IllegalArgumentException, RuntimeException ) +{ + mxObjIdlArray->realloc( array, length ); +} + +sal_Int32 ImplIntrospectionAdapter::getLen(const Any& array) + throw( IllegalArgumentException, RuntimeException ) +{ + return mxObjIdlArray->getLen( array ); +} + +Any ImplIntrospectionAdapter::get(const Any& array, sal_Int32 index) + throw( IllegalArgumentException, ArrayIndexOutOfBoundsException, RuntimeException ) +{ + return mxObjIdlArray->get( array, index ); +} + +void ImplIntrospectionAdapter::set(Any& array, sal_Int32 index, const Any& value) + throw( IllegalArgumentException, ArrayIndexOutOfBoundsException, RuntimeException ) +{ + mxObjIdlArray->set( array, index, value ); +} + + +//************************************************** +//*** Implementation von ImplIntrospectionAccess *** +//************************************************** + +// Methoden von XIntrospectionAccess +sal_Int32 ImplIntrospectionAccess::getSuppliedMethodConcepts(void) + throw( RuntimeException ) +{ + return MethodConcept::DANGEROUS | + PROPERTY | + LISTENER | + ENUMERATION | + NAMECONTAINER | + INDEXCONTAINER; +} + +sal_Int32 ImplIntrospectionAccess::getSuppliedPropertyConcepts(void) + throw( RuntimeException ) +{ + return PropertyConcept::DANGEROUS | + PROPERTYSET | + ATTRIBUTES | + METHODS; +} + +Property ImplIntrospectionAccess::getProperty(const OUString& Name, sal_Int32 PropertyConcepts) + throw( NoSuchElementException, RuntimeException ) +{ + Property aRet; + sal_Int32 i = mpStaticImpl->getPropertyIndex( Name ); + sal_Bool bFound = sal_False; + if( i != -1 ) + { + sal_Int32 nConcept = mpStaticImpl->getPropertyConcepts().getConstArray()[ i ]; + if( (PropertyConcepts & nConcept) != 0 ) + { + const Property* pProps = mpStaticImpl->getProperties().getConstArray(); + aRet = pProps[ i ]; + bFound = sal_True; + } + } + if( !bFound ) + throw NoSuchElementException() ; + return aRet; +} + +sal_Bool ImplIntrospectionAccess::hasProperty(const OUString& Name, sal_Int32 PropertyConcepts) + throw( RuntimeException ) +{ + sal_Int32 i = mpStaticImpl->getPropertyIndex( Name ); + sal_Bool bRet = sal_False; + if( i != -1 ) + { + sal_Int32 nConcept = mpStaticImpl->getPropertyConcepts().getConstArray()[ i ]; + if( (PropertyConcepts & nConcept) != 0 ) + bRet = sal_True; + } + return bRet; +} + +Sequence< Property > ImplIntrospectionAccess::getProperties(sal_Int32 PropertyConcepts) + throw( RuntimeException ) +{ + // Wenn alle unterstuetzten Konzepte gefordert werden, Sequence einfach durchreichen + sal_Int32 nAllSupportedMask = PROPERTYSET | + ATTRIBUTES | + METHODS; + if( ( PropertyConcepts & nAllSupportedMask ) == nAllSupportedMask ) + { + return mpStaticImpl->getProperties(); + } + + // Gleiche Sequence wie beim vorigen mal? + if( mnLastPropertyConcept == PropertyConcepts ) + { + return maLastPropertySeq; + } + + // Anzahl der zu liefernden Properties + sal_Int32 nCount = 0; + + // Es gibt zur Zeit keine DANGEROUS-Properties + // if( PropertyConcepts & DANGEROUS ) + // nCount += mpStaticImpl->mnDangerousPropCount; + if( PropertyConcepts & PROPERTYSET ) + nCount += mpStaticImpl->mnPropertySetPropCount; + if( PropertyConcepts & ATTRIBUTES ) + nCount += mpStaticImpl->mnAttributePropCount; + if( PropertyConcepts & METHODS ) + nCount += mpStaticImpl->mnMethodPropCount; + + // Sequence entsprechend der geforderten Anzahl reallocieren + ImplIntrospectionAccess* pThis = (ImplIntrospectionAccess*)this; // const umgehen + pThis->maLastPropertySeq.realloc( nCount ); + Property* pDestProps = pThis->maLastPropertySeq.getArray(); + + // Alle Properties durchgehen und entsprechend der Concepte uebernehmen + Sequence<Property> aPropSeq = mpStaticImpl->getProperties(); + const Property* pSourceProps = aPropSeq.getConstArray(); + const sal_Int32* pConcepts = mpStaticImpl->getPropertyConcepts().getConstArray(); + sal_Int32 nLen = aPropSeq.getLength(); + + sal_Int32 iDest = 0; + for( sal_Int32 i = 0 ; i < nLen ; i++ ) + { + sal_Int32 nConcept = pConcepts[ i ]; + if( nConcept & PropertyConcepts ) + pDestProps[ iDest++ ] = pSourceProps[ i ]; + + /* + // Property mit Concepts ausgeben + OUString aPropName = pSourceProps[ i ].Name; + String aNameStr = OOUStringToString(aPropName, CHARSET_SYSTEM); + String ConceptStr; + if( nConcept & PROPERTYSET ) + ConceptStr += "PROPERTYSET"; + if( nConcept & ATTRIBUTES ) + ConceptStr += "ATTRIBUTES"; + if( nConcept & METHODS ) + ConceptStr += "METHODS"; + printf( "Property %ld: %s, Concept = %s\n", i, aNameStr.GetStr(), ConceptStr.GetStr() ); + */ + } + + // PropertyConcept merken, dies entspricht maLastPropertySeq + pThis->mnLastPropertyConcept = PropertyConcepts; + + // Zusammengebastelte Sequence liefern + return maLastPropertySeq; +} + +Reference<XIdlMethod> ImplIntrospectionAccess::getMethod(const OUString& Name, sal_Int32 MethodConcepts) + throw( NoSuchMethodException, RuntimeException ) +{ + Reference<XIdlMethod> xRet; + sal_Int32 i = mpStaticImpl->getMethodIndex( Name ); + if( i != -1 ) + { + + sal_Int32 nConcept = mpStaticImpl->getMethodConcepts().getConstArray()[ i ]; + if( (MethodConcepts & nConcept) != 0 ) + { + const Reference<XIdlMethod>* pMethods = mpStaticImpl->getMethods().getConstArray(); + xRet = pMethods[i]; + } + } + if( !xRet.is() ) + throw NoSuchMethodException(); + return xRet; +} + +sal_Bool ImplIntrospectionAccess::hasMethod(const OUString& Name, sal_Int32 MethodConcepts) + throw( RuntimeException ) +{ + sal_Int32 i = mpStaticImpl->getMethodIndex( Name ); + sal_Bool bRet = sal_False; + if( i != -1 ) + { + sal_Int32 nConcept = mpStaticImpl->getMethodConcepts().getConstArray()[ i ]; + if( (MethodConcepts & nConcept) != 0 ) + bRet = sal_True; + } + return bRet; +} + +Sequence< Reference<XIdlMethod> > ImplIntrospectionAccess::getMethods(sal_Int32 MethodConcepts) + throw( RuntimeException ) +{ + ImplIntrospectionAccess* pThis = (ImplIntrospectionAccess*)this; // const umgehen + + // Wenn alle unterstuetzten Konzepte gefordert werden, Sequence einfach durchreichen + sal_Int32 nAllSupportedMask = MethodConcept::DANGEROUS | + PROPERTY | + LISTENER | + ENUMERATION | + NAMECONTAINER | + INDEXCONTAINER | + MethodConcept_NORMAL_IMPL; + if( ( MethodConcepts & nAllSupportedMask ) == nAllSupportedMask ) + { + return mpStaticImpl->getMethods(); + } + + // Gleiche Sequence wie beim vorigen mal? + if( mnLastMethodConcept == MethodConcepts ) + { + return maLastMethodSeq; + } + + // Methoden-Sequences besorgen + Sequence< Reference<XIdlMethod> > aMethodSeq = mpStaticImpl->getMethods(); + const Reference<XIdlMethod>* pSourceMethods = aMethodSeq.getConstArray(); + const sal_Int32* pConcepts = mpStaticImpl->getMethodConcepts().getConstArray(); + sal_Int32 nLen = aMethodSeq.getLength(); + + // Sequence entsprechend der geforderten Anzahl reallocieren + // Anders als bei den Properties kann die Anzahl nicht durch + // Zaehler in inspect() vorher ermittelt werden, da Methoden + // mehreren Konzepten angehoeren koennen + pThis->maLastMethodSeq.realloc( nLen ); + Reference<XIdlMethod>* pDestMethods = pThis->maLastMethodSeq.getArray(); + + // Alle Methods durchgehen und entsprechend der Concepte uebernehmen + sal_Int32 iDest = 0; + for( sal_Int32 i = 0 ; i < nLen ; i++ ) + { + sal_Int32 nConcept = pConcepts[ i ]; + if( nConcept & MethodConcepts ) + pDestMethods[ iDest++ ] = pSourceMethods[ i ]; + + #if OSL_DEBUG_LEVEL > 0 + static bool debug = false; + if ( debug ) + { + // Methode mit Concepts ausgeben + const Reference< XIdlMethod >& rxMethod = pSourceMethods[ i ]; + ::rtl::OString aNameStr = ::rtl::OUStringToOString( rxMethod->getName(), osl_getThreadTextEncoding() ); + ::rtl::OString ConceptStr; + if( nConcept & MethodConcept::DANGEROUS ) + ConceptStr += "DANGEROUS |"; + if( nConcept & MethodConcept::PROPERTY ) + ConceptStr += "PROPERTY |"; + if( nConcept & MethodConcept::LISTENER ) + ConceptStr += "LISTENER |"; + if( nConcept & MethodConcept::ENUMERATION ) + ConceptStr += "ENUMERATION |"; + if( nConcept & MethodConcept::NAMECONTAINER ) + ConceptStr += "NAMECONTAINER |"; + if( nConcept & MethodConcept::INDEXCONTAINER ) + ConceptStr += "INDEXCONTAINER |"; + OSL_TRACE( "Method %ld: %s, Concepts = %s", i, aNameStr.getStr(), ConceptStr.getStr() ); + } + #endif + } + + // Auf die richtige Laenge bringen + pThis->maLastMethodSeq.realloc( iDest ); + + // MethodConcept merken, dies entspricht maLastMethodSeq + pThis->mnLastMethodConcept = MethodConcepts; + + // Zusammengebastelte Sequence liefern + return maLastMethodSeq; +} + +Sequence< Type > ImplIntrospectionAccess::getSupportedListeners(void) + throw( RuntimeException ) +{ + return mpStaticImpl->getSupportedListeners(); +} + +Reference<XInterface> SAL_CALL ImplIntrospectionAccess::queryAdapter( const Type& rType ) + throw( IllegalTypeException, RuntimeException ) +{ + // Gibt es schon einen Adapter? + if( !mpAdapter ) + { + ((ImplIntrospectionAccess*)this)->mpAdapter = + new ImplIntrospectionAdapter( this, maInspectedObject, mpStaticImpl ); + + // Selbst eine Referenz halten + mpAdapter->acquire(); + } + + Reference<XInterface> xRet; + Any aIfaceAny( mpAdapter->queryInterface( rType ) ); + if( aIfaceAny.hasValue() ) + xRet = *(Reference<XInterface>*)aIfaceAny.getValue(); + + return xRet; +} + +// Methoden von XMaterialHolder +Any ImplIntrospectionAccess::getMaterial(void) throw(RuntimeException) +{ + return maInspectedObject; +} + +// Hilfs-Funktion zur LowerCase-Wandlung eines OUString +OUString toLower( OUString aUStr ) +{ + // Tabelle fuer XExactName pflegen + ::rtl::OUString aOWStr( aUStr.getStr() ); + ::rtl::OUString aOWLowerStr = aOWStr.toAsciiLowerCase(); + OUString aLowerUStr( aOWLowerStr.getStr() ); + return aLowerUStr; +} + +// Methoden von XExactName +OUString ImplIntrospectionAccess::getExactName( const OUString& rApproximateName ) throw( RuntimeException ) +{ + OUString aRetStr; + LowerToExactNameMap::iterator aIt = + mpStaticImpl->maLowerToExactNameMap.find( toLower( rApproximateName ) ); + if( !( aIt == mpStaticImpl->maLowerToExactNameMap.end() ) ) + aRetStr = (*aIt).second; + return aRetStr; +} + + +//----------------------------------------------------------------------------- + +#ifdef USE_INTROSPECTION_CACHE + +struct hashIntrospectionKey_Impl +{ + Sequence< Reference<XIdlClass> > aIdlClasses; + Reference<XPropertySetInfo> xPropInfo; + Reference<XIdlClass> xImplClass; + sal_Int32 nHitCount; + + void IncHitCount() const { ((hashIntrospectionKey_Impl*)this)->nHitCount++; } + hashIntrospectionKey_Impl() : nHitCount( 0 ) {} + hashIntrospectionKey_Impl( const Sequence< Reference<XIdlClass> > & rIdlClasses, + const Reference<XPropertySetInfo> & rxPropInfo, + const Reference<XIdlClass> & rxImplClass ); +}; + +hashIntrospectionKey_Impl::hashIntrospectionKey_Impl +( + const Sequence< Reference<XIdlClass> > & rIdlClasses, + const Reference<XPropertySetInfo> & rxPropInfo, + const Reference<XIdlClass> & rxImplClass +) + : aIdlClasses( rIdlClasses ) + , xPropInfo( rxPropInfo ) + , xImplClass( rxImplClass ) + , nHitCount( 0 ) +{} + + +struct hashIntrospectionAccessCache_Impl +{ + size_t operator()(const hashIntrospectionKey_Impl & rObj ) const + { + return (size_t)rObj.xImplClass.get() ^ (size_t)rObj.xPropInfo.get(); + } + + bool operator()( const hashIntrospectionKey_Impl & rObj1, + const hashIntrospectionKey_Impl & rObj2 ) const + { + if( rObj1.xPropInfo != rObj2.xPropInfo + || rObj1.xImplClass != rObj2.xImplClass ) + return sal_False; + + sal_Int32 nCount1 = rObj1.aIdlClasses.getLength(); + sal_Int32 nCount2 = rObj2.aIdlClasses.getLength(); + if( nCount1 != nCount2 ) + return sal_False; + + const Reference<XIdlClass>* pRefs1 = rObj1.aIdlClasses.getConstArray(); + const Reference<XIdlClass>* pRefs2 = rObj2.aIdlClasses.getConstArray(); + return memcmp( pRefs1, pRefs2, nCount1 * sizeof( Reference<XIdlClass> ) ) == 0; + } + +}; + +typedef std::hash_map +< + hashIntrospectionKey_Impl, + IntrospectionAccessStatic_Impl*, + hashIntrospectionAccessCache_Impl, + hashIntrospectionAccessCache_Impl +> +IntrospectionAccessCacheMap_Impl; + +class IntrospectionAccessCacheMap : public IntrospectionAccessCacheMap_Impl +{ +public: + ~IntrospectionAccessCacheMap() + { + IntrospectionAccessCacheMap::iterator iter = begin(); + IntrospectionAccessCacheMap::iterator stop = this->end(); + while( iter != stop ) + { + + (*iter).second->release(); + (*iter).second = NULL; + iter++; + } + } +}; + + +// For XTypeProvider +struct hashTypeProviderKey_Impl +{ + Reference<XPropertySetInfo> xPropInfo; + Sequence< sal_Int8 > maImpIdSeq; + sal_Int32 nHitCount; + + void IncHitCount() const { ((hashTypeProviderKey_Impl*)this)->nHitCount++; } + hashTypeProviderKey_Impl() : nHitCount( 0 ) {} + hashTypeProviderKey_Impl( const Reference<XPropertySetInfo> & rxPropInfo, const Sequence< sal_Int8 > & aImpIdSeq_ ); +}; + +hashTypeProviderKey_Impl::hashTypeProviderKey_Impl +( + const Reference<XPropertySetInfo> & rxPropInfo, + const Sequence< sal_Int8 > & aImpIdSeq_ +) + : xPropInfo( rxPropInfo ) + , maImpIdSeq( aImpIdSeq_ ) + , nHitCount( 0 ) +{} + + +struct TypeProviderAccessCache_Impl +{ + size_t operator()(const hashTypeProviderKey_Impl & rObj ) const; + + bool operator()( const hashTypeProviderKey_Impl & rObj1, + const hashTypeProviderKey_Impl & rObj2 ) const + { + if( rObj1.xPropInfo != rObj2.xPropInfo ) + return sal_False; + + bool bEqual = false; + sal_Int32 nLen1 = rObj1.maImpIdSeq.getLength(); + sal_Int32 nLen2 = rObj2.maImpIdSeq.getLength(); + if( nLen1 == nLen2 && nLen1 > 0 ) + { + const sal_Int8* pId1 = rObj1.maImpIdSeq.getConstArray(); + const sal_Int8* pId2 = rObj2.maImpIdSeq.getConstArray(); + bEqual = (memcmp( pId1, pId2, nLen1 * sizeof( sal_Int8 ) ) == 0 ); + } + return bEqual; + } +}; + +size_t TypeProviderAccessCache_Impl::operator()(const hashTypeProviderKey_Impl & rObj ) const +{ + const sal_Int32* pBytesAsInt32Array = (const sal_Int32*)rObj.maImpIdSeq.getConstArray(); + sal_Int32 nLen = rObj.maImpIdSeq.getLength(); + sal_Int32 nCount32 = nLen / 4; + sal_Int32 nMod32 = nLen % 4; + + // XOR with full 32 bit values + sal_Int32 nId32 = 0; + sal_Int32 i; + for( i = 0 ; i < nCount32 ; i++ ) + nId32 ^= *(pBytesAsInt32Array++); + + // XOR with remaining byte values + if( nMod32 ) + { + const sal_Int8* pBytes = (const sal_Int8*)pBytesAsInt32Array; + sal_Int8* pInt8_Id32 = (sal_Int8*)&nId32; + for( i = 0 ; i < nMod32 ; i++ ) + *(pInt8_Id32++) ^= *(pBytes++); + } + + return (size_t)nId32; +} + + +typedef std::hash_map +< + hashTypeProviderKey_Impl, + IntrospectionAccessStatic_Impl*, + TypeProviderAccessCache_Impl, + TypeProviderAccessCache_Impl +> +TypeProviderAccessCacheMap_Impl; + +class TypeProviderAccessCacheMap : public TypeProviderAccessCacheMap_Impl +{ +public: + ~TypeProviderAccessCacheMap() + { + TypeProviderAccessCacheMap::iterator iter = begin(); + TypeProviderAccessCacheMap::iterator stop = this->end(); + while( iter != stop ) + { + (*iter).second->release(); + (*iter).second = NULL; + iter++; + } + } +}; + +#endif + + +//************************* +//*** ImplIntrospection *** +//************************* + +struct OIntrospectionMutex +{ + Mutex m_mutex; +}; + +class ImplIntrospection : public XIntrospection + , public XServiceInfo + , public OIntrospectionMutex + , public OComponentHelper +{ + friend class ImplMergeIntrospection; + friend class ImplMVCIntrospection; + + // Implementation der Introspection. + // ACHTUNG: RefCounting von Hand !!! + IntrospectionAccessStatic_Impl* implInspect(const Any& aToInspectObj); + + // Save XMultiServiceFactory from createComponent + Reference<XMultiServiceFactory> m_xSMgr; + + // CoreReflection halten + Reference< XIdlReflection > mxCoreReflection; + + // Klassen, deren Methoden eine spezielle Rolle spielen + Reference<XIdlClass> mxElementAccessClass; + Reference<XIdlClass> mxNameContainerClass; + Reference<XIdlClass> mxNameAccessClass; + Reference<XIdlClass> mxIndexContainerClass; + Reference<XIdlClass> mxIndexAccessClass; + Reference<XIdlClass> mxEnumerationAccessClass; + Reference<XIdlClass> mxInterfaceClass; + Reference<XIdlClass> mxAggregationClass; + sal_Bool mbDisposed; + +#ifdef USE_INTROSPECTION_CACHE + sal_uInt16 mnCacheEntryCount; + sal_uInt16 mnTPCacheEntryCount; + IntrospectionAccessCacheMap* mpCache; + TypeProviderAccessCacheMap* mpTypeProviderCache; +#endif + +public: + ImplIntrospection( const Reference<XMultiServiceFactory> & rXSMgr ); + + // Methoden von XInterface + virtual Any SAL_CALL queryInterface( const Type& rType ) throw( RuntimeException ); + virtual void SAL_CALL acquire() throw() { OComponentHelper::acquire(); } + virtual void SAL_CALL release() throw() { OComponentHelper::release(); } + + // XTypeProvider + Sequence< Type > SAL_CALL getTypes( ) throw( RuntimeException ); + Sequence<sal_Int8> SAL_CALL getImplementationId( ) throw( RuntimeException ); + + // XServiceInfo + OUString SAL_CALL getImplementationName() throw(); + sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw(); + Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw(); + static OUString SAL_CALL getImplementationName_Static( ); + static Sequence< OUString > SAL_CALL getSupportedServiceNames_Static(void) throw(); + + // Methoden von XIntrospection + virtual Reference<XIntrospectionAccess> SAL_CALL inspect(const Any& aToInspectObj) + throw( RuntimeException ); + +protected: + // some XComponent part from OComponentHelper + virtual void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException); +}; + +enum MethodType +{ + STANDARD_METHOD, // normale Methode, kein Bezug zu Properties oder Listenern + GETSET_METHOD, // gehoert zu einer get/set-Property + ADD_LISTENER_METHOD, // add-Methode einer Listener-Schnittstelle + REMOVE_LISTENER_METHOD, // remove-Methode einer Listener-Schnittstelle + INVALID_METHOD // Methode, deren Klasse nicht beruecksichtigt wird, z.B. XPropertySet +}; + +// Ctor +ImplIntrospection::ImplIntrospection( const Reference<XMultiServiceFactory> & rXSMgr ) + : OComponentHelper( m_mutex ) + , m_xSMgr( rXSMgr ) +{ +#ifdef USE_INTROSPECTION_CACHE + mnCacheEntryCount = 0; + mnTPCacheEntryCount = 0; + mpCache = NULL; + mpTypeProviderCache = NULL; +#endif + + // Spezielle Klassen holen +// Reference< XInterface > xServiceIface = m_xSMgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.reflection.CoreReflection")) ); +// if( xServiceIface.is() ) +// mxCoreReflection = Reference< XIdlReflection >::query( xServiceIface ); + Reference< XPropertySet > xProps( rXSMgr, UNO_QUERY ); + OSL_ASSERT( xProps.is() ); + if (xProps.is()) + { + Reference< XComponentContext > xContext; + xProps->getPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xContext; + OSL_ASSERT( xContext.is() ); + if (xContext.is()) + { + xContext->getValueByName( + OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theCoreReflection") ) ) >>= mxCoreReflection; + OSL_ENSURE( mxCoreReflection.is(), "### CoreReflection singleton not accessible!?" ); + } + } + if (! mxCoreReflection.is()) + { + throw DeploymentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theCoreReflection singleton not accessible") ), + Reference< XInterface >() ); + } + + mxElementAccessClass = mxCoreReflection->forName( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.XElementAccess")) ); + mxNameContainerClass = mxCoreReflection->forName( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.XNameContainer")) ); + mxNameAccessClass = mxCoreReflection->forName( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.XNameAccess")) ); + mxIndexContainerClass = mxCoreReflection->forName( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.XIndexContainer")) ); + mxIndexAccessClass = mxCoreReflection->forName( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.XIndexAccess")) ); + mxEnumerationAccessClass = mxCoreReflection->forName( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.container.XEnumerationAccess")) ); + mxInterfaceClass = mxCoreReflection->forName( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.XInterface")) ); + mxAggregationClass = mxCoreReflection->forName( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.XAggregation")) ); + mbDisposed = sal_False; +} + +// XComponent +void ImplIntrospection::dispose() throw(::com::sun::star::uno::RuntimeException) +{ + OComponentHelper::dispose(); + +#ifdef USE_INTROSPECTION_CACHE + // Cache loeschen + delete mpCache; + mpCache = NULL; + delete mpTypeProviderCache; + mpTypeProviderCache = NULL; +#endif + + mxElementAccessClass = NULL; + mxNameContainerClass = NULL; + mxNameAccessClass = NULL; + mxIndexContainerClass = NULL; + mxIndexAccessClass = NULL; + mxEnumerationAccessClass = NULL; + mxInterfaceClass = NULL; + mxAggregationClass = NULL; + mbDisposed = sal_True; +} + + +//----------------------------------------------------------------------------- + +// XInterface +Any ImplIntrospection::queryInterface( const Type & rType ) + throw(::com::sun::star::uno::RuntimeException) +{ + Any aRet( ::cppu::queryInterface( + rType, + static_cast< XIntrospection * >( this ), + static_cast< XServiceInfo * >( this ) ) ); + + return (aRet.hasValue() ? aRet : OComponentHelper::queryInterface( rType )); +} + +// XTypeProvider +Sequence< Type > ImplIntrospection::getTypes() + throw( RuntimeException ) +{ + static OTypeCollection * s_pTypes = 0; + if (! s_pTypes) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! s_pTypes) + { + static OTypeCollection s_aTypes( + ::getCppuType( (const Reference< XIntrospection > *)0 ), + ::getCppuType( (const Reference< XServiceInfo > *)0 ), + OComponentHelper::getTypes() ); + s_pTypes = &s_aTypes; + } + } + return s_pTypes->getTypes(); +} + +Sequence< sal_Int8 > ImplIntrospection::getImplementationId() + throw( RuntimeException ) +{ + static OImplementationId * s_pId = 0; + if (! s_pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! s_pId) + { + static OImplementationId s_aId; + s_pId = &s_aId; + } + } + return s_pId->getImplementationId(); +} + + +// XServiceInfo +OUString ImplIntrospection::getImplementationName() throw() +{ + return getImplementationName_Static(); +} + +// XServiceInfo +sal_Bool ImplIntrospection::supportsService(const OUString& ServiceName) throw() +{ + Sequence< OUString > aSNL = getSupportedServiceNames(); + const OUString * pArray = aSNL.getConstArray(); + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return sal_True; + return sal_False; +} + +// XServiceInfo +Sequence< OUString > ImplIntrospection::getSupportedServiceNames(void) throw() +{ + return getSupportedServiceNames_Static(); +} + +//************************************************************************* +// Helper XServiceInfo +OUString ImplIntrospection::getImplementationName_Static( ) +{ + return OUString::createFromAscii( IMPLEMENTATION_NAME ); +} + +// ORegistryServiceManager_Static +Sequence< OUString > ImplIntrospection::getSupportedServiceNames_Static(void) throw() +{ + Sequence< OUString > aSNS( 1 ); + aSNS.getArray()[0] = OUString::createFromAscii( SERVICE_NAME ); + return aSNS; +} + +//************************************************************************* + +// Methoden von XIntrospection +Reference<XIntrospectionAccess> ImplIntrospection::inspect(const Any& aToInspectObj) + throw( RuntimeException ) +{ + Reference<XIntrospectionAccess> xAccess; + + if ( aToInspectObj.getValueType().getTypeClass() == TypeClass_TYPE ) + { + Type aType; + aToInspectObj >>= aType; + + Reference< XIdlClass > xIdlClass = mxCoreReflection->forName(((Type*)(aToInspectObj.getValue()))->getTypeName()); + + if ( xIdlClass.is() ) + { + Any aRealInspectObj; + aRealInspectObj <<= xIdlClass; + + IntrospectionAccessStatic_Impl* pStaticImpl = implInspect( aRealInspectObj ); + if( pStaticImpl ) + xAccess = new ImplIntrospectionAccess( aRealInspectObj, pStaticImpl ); + } + } + else + { + IntrospectionAccessStatic_Impl* pStaticImpl = implInspect( aToInspectObj ); + if( pStaticImpl ) + xAccess = new ImplIntrospectionAccess( aToInspectObj, pStaticImpl ); + } + + return xAccess; +} + +//----------------------------------------------------------------------------- + +// Hashtable fuer Pruefung auf mehrfache Beruecksichtigung von Interfaces +struct hashInterface_Impl +{ + size_t operator()(const void* p) const + { + return (size_t)p; + } +}; + +struct eqInterface_Impl +{ + bool operator()(const void* p1, const void* p2) const + { + return ( p1 == p2 ); + } +}; + +typedef std::hash_map +< + void*, + void*, + hashInterface_Impl, + eqInterface_Impl +> +CheckedInterfacesMap; + + + +// TODO: Spaeter auslagern +Reference<XIdlClass> TypeToIdlClass( const Type& rType, const Reference< XMultiServiceFactory > & xMgr ) +{ + static Reference< XIdlReflection > xRefl; + + // void als Default-Klasse eintragen + Reference<XIdlClass> xRetClass; + typelib_TypeDescription * pTD = 0; + rType.getDescription( &pTD ); + if( pTD ) + { + OUString sOWName( pTD->pTypeName ); + if( !xRefl.is() ) + { + xRefl = Reference< XIdlReflection >( xMgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.reflection.CoreReflection")) ), UNO_QUERY ); + OSL_ENSURE( xRefl.is(), "### no corereflection!" ); + } + xRetClass = xRefl->forName( sOWName ); + } + return xRetClass; +} + +// Implementation der Introspection. +IntrospectionAccessStatic_Impl* ImplIntrospection::implInspect(const Any& aToInspectObj) +{ + MutexGuard aGuard( m_mutex ); + + // Wenn die Introspection schon disposed ist, wird nur ein leeres Ergebnis geliefert + if( mbDisposed ) + return NULL; + + // Objekt untersuchen + TypeClass eType = aToInspectObj.getValueType().getTypeClass(); + if( eType != TypeClass_INTERFACE && eType != TypeClass_STRUCT && eType != TypeClass_EXCEPTION ) + return NULL; + + Reference<XInterface> x; + if( eType == TypeClass_INTERFACE ) + { + // Interface aus dem Any besorgen + x = *(Reference<XInterface>*)aToInspectObj.getValue(); + if( !x.is() ) + return NULL; + } + +#ifdef USE_INTROSPECTION_CACHE + // Haben wir schon eine Cache-Instanz + if( !mpCache ) + mpCache = new IntrospectionAccessCacheMap; + if( !mpTypeProviderCache ) + mpTypeProviderCache = new TypeProviderAccessCacheMap; + IntrospectionAccessCacheMap& aCache = *mpCache; + TypeProviderAccessCacheMap& aTPCache = *mpTypeProviderCache; + + // Pointer auf ggf. noetige neue IntrospectionAccess-Instanz + IntrospectionAccessStatic_Impl* pAccess = NULL; +#else + // Pointer auf ggf. noetige neue IntrospectionAccess-Instanz + IntrospectionAccessStatic_Impl* pAccess = new IntrospectionAccessStatic_Impl( mxCoreReflection ); +#endif + + // Pruefen: Ist schon ein passendes Access-Objekt gecached? + Sequence< Reference<XIdlClass> > SupportedClassSeq; + Sequence< Type > SupportedTypesSeq; + Reference<XIdlClassProvider> xClassProvider; + Reference<XTypeProvider> xTypeProvider; + Reference<XIdlClass> xImplClass; + Reference<XPropertySetInfo> xPropSetInfo; + Reference<XPropertySet> xPropSet; + + // Bei Interfaces XTypeProvider / XIdlClassProvider- und PropertySet-Interface anfordern + if( eType == TypeClass_INTERFACE ) + { + // XIdlClassProvider + xTypeProvider = Reference<XTypeProvider>::query( x ); + if( xTypeProvider.is() ) + { + SupportedTypesSeq = xTypeProvider->getTypes(); + sal_Int32 nTypeCount = SupportedTypesSeq.getLength(); + if( nTypeCount ) + { + SupportedClassSeq.realloc( nTypeCount ); + Reference<XIdlClass>* pClasses = SupportedClassSeq.getArray(); + + const Type* pTypes = SupportedTypesSeq.getConstArray(); + for( sal_Int32 i = 0 ; i < nTypeCount ; i++ ) + { + pClasses[ i ] = TypeToIdlClass( pTypes[ i ], m_xSMgr ); + } + // TODO: Caching! + } + } + else + { + // XIdlClassProvider + xClassProvider = Reference<XIdlClassProvider>::query( x ); + if( xClassProvider.is() ) + { + SupportedClassSeq = xClassProvider->getIdlClasses(); + if( SupportedClassSeq.getLength() ) + xImplClass = SupportedClassSeq.getConstArray()[0]; + } + } + // #70197, fuer InvocationAdapter: Interface-Typ im Any auch ohne + // ClassProvider unterstuetzen + if( !xClassProvider.is() && !xTypeProvider.is() ) + { + xImplClass = TypeToIdlClass( aToInspectObj.getValueType(), m_xSMgr ); + SupportedClassSeq.realloc( 1 ); + SupportedClassSeq.getArray()[ 0 ] = xImplClass; + } + + xPropSet = Reference<XPropertySet>::query( x ); + // Jetzt versuchen, das PropertySetInfo zu bekommen + if( xPropSet.is() ) + xPropSetInfo = xPropSet->getPropertySetInfo(); + } + else + { + xImplClass = TypeToIdlClass( aToInspectObj.getValueType(), m_xSMgr ); + } + +#ifdef USE_INTROSPECTION_CACHE + if( xTypeProvider.is() ) + { + Sequence< sal_Int8 > aImpIdSeq = xTypeProvider->getImplementationId(); + sal_Int32 nIdLen = aImpIdSeq.getLength(); + + if( nIdLen ) + { + // cache only, if the descriptor class is set + hashTypeProviderKey_Impl aKeySeq( xPropSetInfo, aImpIdSeq ); + + TypeProviderAccessCacheMap::iterator aIt = aTPCache.find( aKeySeq ); + if( aIt == aTPCache.end() ) + { + // not found + // Neue Instanz anlegen und unter dem gegebenen Key einfuegen + pAccess = new IntrospectionAccessStatic_Impl( mxCoreReflection ); + + // RefCount von Hand erhoehen, muss beim Entfernen + // aus der Hashtable wieder released werden + pAccess->acquire(); + + // Groesse begrenzen, alten Eintrag wieder rausschmeissen + if( mnTPCacheEntryCount > INTROSPECTION_CACHE_MAX_SIZE ) + { + // Access mit dem kleinsten HitCount suchen + TypeProviderAccessCacheMap::iterator iter = aTPCache.begin(); + TypeProviderAccessCacheMap::iterator end = aTPCache.end(); + TypeProviderAccessCacheMap::iterator toDelete = iter; + while( iter != end ) + { + if( (*iter).first.nHitCount < (*toDelete).first.nHitCount ) + toDelete = iter; + ++iter; + } + + // Gefundenen Eintrag entfernen + if( (*toDelete).second ) + (*toDelete).second->release(); + (*toDelete).second = NULL; + aTPCache.erase( toDelete ); + } + else + mnTPCacheEntryCount++; + + // Neuer Eintrage rein in die Table + aKeySeq.nHitCount = 1; + aTPCache[ aKeySeq ] = pAccess; + + } + else + { + // Hit-Count erhoehen + (*aIt).first.IncHitCount(); + return (*aIt).second; + } + } + } + else if( xImplClass.is() ) + { + // cache only, if the descriptor class is set + hashIntrospectionKey_Impl aKeySeq( SupportedClassSeq, xPropSetInfo, xImplClass ); + + IntrospectionAccessCacheMap::iterator aIt = aCache.find( aKeySeq ); + if( aIt == aCache.end() ) + { + // not found + // Neue Instanz anlegen und unter dem gegebenen Key einfuegen + pAccess = new IntrospectionAccessStatic_Impl( mxCoreReflection ); + + // RefCount von Hand erhoehen, muss beim Entfernen + // aus der Hashtable wieder released werden + pAccess->acquire(); + + // Groesse begrenzen, alten Eintrag wieder rausschmeissen + if( mnCacheEntryCount > INTROSPECTION_CACHE_MAX_SIZE ) + { + // Access mit dem kleinsten HitCount suchen + IntrospectionAccessCacheMap::iterator iter = aCache.begin(); + IntrospectionAccessCacheMap::iterator end = aCache.end(); + IntrospectionAccessCacheMap::iterator toDelete = iter; + while( iter != end ) + { + if( (*iter).first.nHitCount < (*toDelete).first.nHitCount ) + toDelete = iter; + ++iter; + } + + // Gefundenen Eintrag entfernen + if( (*toDelete).second ) + (*toDelete).second->release(); + (*toDelete).second = NULL; + aCache.erase( toDelete ); + } + else + mnCacheEntryCount++; + + // Neuer Eintrage rein in die Table + aKeySeq.nHitCount = 1; + aCache[ aKeySeq ] = pAccess; + + } + else + { + // Hit-Count erhoehen + (*aIt).first.IncHitCount(); + return (*aIt).second; + } + } +#endif + + // Kein Access gecached -> neu anlegen + Property* pAllPropArray; + Reference<XInterface>* pInterfaces1; + Reference<XInterface>* pInterfaces2; + sal_Int16* pMapTypeArray; + sal_Int32* pPropertyConceptArray; + sal_Int32 i; + + if( !pAccess ) + pAccess = new IntrospectionAccessStatic_Impl( mxCoreReflection ); + + // Referenzen auf wichtige Daten von pAccess + sal_Int32& rPropCount = pAccess->mnPropCount; + IntrospectionNameMap& rPropNameMap = pAccess->maPropertyNameMap; + IntrospectionNameMap& rMethodNameMap = pAccess->maMethodNameMap; + LowerToExactNameMap& rLowerToExactNameMap = pAccess->maLowerToExactNameMap; + + // Schon mal Pointer auf das eigene Property-Feld holen + pAllPropArray = pAccess->maAllPropertySeq.getArray(); + pInterfaces1 = pAccess->aInterfaceSeq1.getArray(); + pInterfaces2 = pAccess->aInterfaceSeq2.getArray(); + pMapTypeArray = pAccess->maMapTypeSeq.getArray(); + pPropertyConceptArray = pAccess->maPropertyConceptSeq.getArray(); + + //************************* + //*** Analyse vornehmen *** + //************************* + if( eType == TypeClass_INTERFACE ) + { + // Zunaechst nach speziellen Interfaces suchen, die fuer + // die Introspection von besonderer Bedeutung sind. + + // XPropertySet vorhanden? + if( xPropSet.is() && xPropSetInfo.is() ) + { + // Gibt es auch ein FastPropertySet? + Reference<XFastPropertySet> xDummy = Reference<XFastPropertySet>::query( x ); + sal_Bool bFast = pAccess->mbFastPropSet = xDummy.is(); + + Sequence<Property> aPropSeq = xPropSetInfo->getProperties(); + const Property* pProps = aPropSeq.getConstArray(); + sal_Int32 nLen = aPropSeq.getLength(); + + // Bei FastPropertySet muessen wir uns die Original-Handles merken + if( bFast ) + pAccess->mpOrgPropertyHandleArray = new sal_Int32[ nLen ]; + + for( i = 0 ; i < nLen ; i++ ) + { + // Property in eigene Liste uebernehmen + pAccess->checkPropertyArraysSize + ( pAllPropArray, pMapTypeArray, pPropertyConceptArray, rPropCount ); + Property& rProp = pAllPropArray[ rPropCount ]; + rProp = pProps[ i ]; + + if( bFast ) + pAccess->mpOrgPropertyHandleArray[ i ] = rProp.Handle; + + // PropCount als Handle fuer das eigene FastPropertySet eintragen + rProp.Handle = rPropCount; + + // Art der Property merken + pMapTypeArray[ rPropCount ] = MAP_PROPERTY_SET; + pPropertyConceptArray[ rPropCount ] = PROPERTYSET; + pAccess->mnPropertySetPropCount++; + + // Namen in Hashtable eintragen, wenn nicht schon bekannt + OUString aPropName = rProp.Name; + + // Haben wir den Namen schon? + IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName ); + if( aIt == rPropNameMap.end() ) + { + // Neuer Eintrag in die Hashtable + rPropNameMap[ aPropName ] = rPropCount; + + // Tabelle fuer XExactName pflegen + rLowerToExactNameMap[ toLower( aPropName ) ] = aPropName; + } + else + { + OSL_ENSURE( sal_False, + OString( "Introspection: Property \"" ) + + OUStringToOString( aPropName, RTL_TEXTENCODING_ASCII_US ) + + OString( "\" found more than once in PropertySet" ) ); + } + + // Count pflegen + rPropCount++; + } + } + + + // Jetzt alle weiteren implementierten Interfaces durchgehen + // Diese muessen durch das XIdlClassProvider-Interface geliefert werden. + // #70197, fuer InvocationAdapter: Interface-Typ im Any auch ohne + // ClassProvider unterstuetzen + //if( xClassProvider.is() ) + { + // Indizes in die Export-Tabellen + sal_Int32 iAllExportedMethod = 0; + sal_Int32 iAllSupportedListener = 0; + + // Hashtable fuer Pruefung auf mehrfache Beruecksichtigung von Interfaces + CheckedInterfacesMap aCheckedInterfacesMap; + + // Flag, ob XInterface-Methoden erfasst werden sollen + // (das darf nur einmal erfolgen, initial zulassen) + sal_Bool bXInterfaceIsInvalid = sal_False; + + // Flag, ob die XInterface-Methoden schon erfasst wurden. Wenn sal_True, + // wird bXInterfaceIsInvalid am Ende der Iface-Schleife aktiviert und + // XInterface-Methoden werden danach abgeklemmt. + sal_Bool bFoundXInterface = sal_False; + + // Schleife ueber alle vom ClassProvider angegebenen Klassen + sal_Int32 nClassCount = SupportedClassSeq.getLength(); + for( sal_Int32 nIdx = 0 ; nIdx < nClassCount; nIdx++ ) + { + Reference<XIdlClass> xImplClass2 = SupportedClassSeq.getConstArray()[nIdx]; + while( xImplClass2.is() ) + { + // Interfaces der Implementation holen + Sequence< Reference<XIdlClass> > aClassSeq = xImplClass2->getInterfaces(); + sal_Int32 nIfaceCount = aClassSeq.getLength(); + + aClassSeq.realloc( nIfaceCount + 1 ); + aClassSeq.getArray()[ nIfaceCount ] = xImplClass2; + nIfaceCount++; + + const Reference<XIdlClass>* pParamArray = aClassSeq.getConstArray(); + + for( sal_Int32 j = 0 ; j < nIfaceCount ; j++ ) + { + const Reference<XIdlClass>& rxIfaceClass = pParamArray[j]; + + // Pruefen, ob das Interface schon beruecksichtigt wurde. + XInterface* pIface = SAL_STATIC_CAST( XInterface*, rxIfaceClass.get() ); + if( aCheckedInterfacesMap.count( pIface ) > 0 ) + { + // Kennen wir schon + continue; + } + else + { + // Sonst eintragen + aCheckedInterfacesMap[ pIface ] = pIface; + } + + //******************************************************************** + + // 2. Fields als Properties registrieren + + // Felder holen + Sequence< Reference<XIdlField> > fields = rxIfaceClass->getFields(); + const Reference<XIdlField>* pFields = fields.getConstArray(); + sal_Int32 nLen = fields.getLength(); + + for( i = 0 ; i < nLen ; i++ ) + { + Reference<XIdlField> xField = pFields[i]; + Reference<XIdlClass> xPropType = xField->getType(); + + // Ist die PropertySequence gross genug? + pAccess->checkPropertyArraysSize + ( pAllPropArray, pMapTypeArray, pPropertyConceptArray, rPropCount ); + + // In eigenes Property-Array eintragen + Property& rProp = pAllPropArray[ rPropCount ]; + OUString aFieldName = xField->getName(); + rProp.Name = aFieldName; + rProp.Handle = rPropCount; + Type aFieldType( xPropType->getTypeClass(), xPropType->getName() ); + rProp.Type = aFieldType; + FieldAccessMode eAccessMode = xField->getAccessMode(); + rProp.Attributes = (eAccessMode == FieldAccessMode_READONLY || + eAccessMode == FieldAccessMode_CONST) + ? READONLY : 0; + + // Namen in Hashtable eintragen + OUString aPropName = rProp.Name; + + // Haben wir den Namen schon? + IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName ); + if( !( aIt == rPropNameMap.end() ) ) + { + /* TODO + OSL_TRACE( + String( "Introspection: Property \"" ) + + OOUStringToString( aPropName, CHARSET_SYSTEM ) + + String( "\" found more than once" ) ); + */ + continue; + } + + // Neuer Eintrag in die Hashtable + rPropNameMap[ aPropName ] = rPropCount; + + // Tabelle fuer XExactName pflegen + rLowerToExactNameMap[ toLower( aPropName ) ] = aPropName; + + // Field merken + pAccess->checkInterfaceArraySize( pAccess->aInterfaceSeq1, + pInterfaces1, rPropCount ); + pInterfaces1[ rPropCount ] = xField; + + // Art der Property merken + pMapTypeArray[ rPropCount ] = MAP_FIELD; + pPropertyConceptArray[ rPropCount ] = ATTRIBUTES; + pAccess->mnAttributePropCount++; + + // Count pflegen + rPropCount++; + } + + //******************************************************************** + + // 3. Methoden + + // Zaehler fuer die gefundenen Listener + sal_Int32 nListenerCount = 0; + + // Alle Methoden holen und merken + Sequence< Reference<XIdlMethod> > methods = rxIfaceClass->getMethods(); + const Reference<XIdlMethod>* pSourceMethods = methods.getConstArray(); + sal_Int32 nSourceMethodCount = methods.getLength(); + + // 3. a) get/set- und Listener-Methoden suchen + + // Feld fuer Infos ueber die Methoden anlegen, damit spaeter leicht die Methoden + // gefunden werden koennen, die nicht im Zusammenhang mit Properties oder Listenern + // stehen. NEU: auch MethodConceptArray initialisieren + MethodType* pMethodTypes = new MethodType[ nSourceMethodCount ]; + sal_Int32* pLocalMethodConcepts = new sal_Int32[ nSourceMethodCount ]; + for( i = 0 ; i < nSourceMethodCount ; i++ ) + { + pMethodTypes[ i ] = STANDARD_METHOD; + pLocalMethodConcepts[ i ] = 0; + } + + OUString aMethName; + OUString aPropName; + OUString aStartStr; + for( i = 0 ; i < nSourceMethodCount ; i++ ) + { + // Methode ansprechen + const Reference<XIdlMethod>& rxMethod_i = pSourceMethods[i]; + sal_Int32& rMethodConcept_i = pLocalMethodConcepts[ i ]; + + // Namen besorgen + aMethName = rxMethod_i->getName(); + + // Methoden katalogisieren + // Alle (?) Methoden von XInterface filtern, damit z.B. nicht + // vom Scripting aus aquire oder release gerufen werden kann + if( rxMethod_i->getDeclaringClass()->equals( mxInterfaceClass ) ) + { + // XInterface-Methoden sind hiermit einmal beruecksichtigt + bFoundXInterface = sal_True; + + if( bXInterfaceIsInvalid ) + { + pMethodTypes[ i ] = INVALID_METHOD; + continue; + } + else + { + if( aMethName != OUString( RTL_CONSTASCII_USTRINGPARAM("queryInterface")) ) + { + rMethodConcept_i |= MethodConcept::DANGEROUS; + continue; + } + } + } + else if( rxMethod_i->getDeclaringClass()->equals( mxAggregationClass ) ) + { + if( aMethName == OUString( RTL_CONSTASCII_USTRINGPARAM("setDelegator")) ) + { + rMethodConcept_i |= MethodConcept::DANGEROUS; + continue; + } + } + else if( rxMethod_i->getDeclaringClass()->equals( mxElementAccessClass ) ) + { + rMethodConcept_i |= ( NAMECONTAINER | + INDEXCONTAINER | + ENUMERATION ); + } + else if( rxMethod_i->getDeclaringClass()->equals( mxNameContainerClass ) || + rxMethod_i->getDeclaringClass()->equals( mxNameAccessClass ) ) + { + rMethodConcept_i |= NAMECONTAINER; + } + else if( rxMethod_i->getDeclaringClass()->equals( mxIndexContainerClass ) || + rxMethod_i->getDeclaringClass()->equals( mxIndexAccessClass ) ) + { + rMethodConcept_i |= INDEXCONTAINER; + } + else if( rxMethod_i->getDeclaringClass()->equals( mxEnumerationAccessClass ) ) + { + rMethodConcept_i |= ENUMERATION; + } + + // Wenn der Name zu kurz ist, wird's sowieso nichts + if( aMethName.getLength() <= 3 ) + continue; + + // Ist es eine get-Methode? + aStartStr = aMethName.copy( 0, 3 ); + if( aStartStr == OUString( RTL_CONSTASCII_USTRINGPARAM("get")) ) + { + // Namen der potentiellen Property + aPropName = aMethName.copy( 3 ); + + // get-Methode darf keinen Parameter haben + Sequence< Reference<XIdlClass> > getParams = rxMethod_i->getParameterTypes(); + if( getParams.getLength() > 0 ) + { + continue; + } + + // Haben wir den Namen schon? + IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName ); + if( !( aIt == rPropNameMap.end() ) ) + { + /* TODO + OSL_TRACE( + String( "Introspection: Property \"" ) + + OOUStringToString( aPropName, CHARSET_SYSTEM ) + + String( "\" found more than once" ) ); + */ + continue; + } + + // Eine readonly-Property ist es jetzt mindestens schon + rMethodConcept_i |= PROPERTY; + + pMethodTypes[i] = GETSET_METHOD; + Reference<XIdlClass> xGetRetType = rxMethod_i->getReturnType(); + + // Ist die PropertySequence gross genug? + pAccess->checkPropertyArraysSize + ( pAllPropArray, pMapTypeArray, pPropertyConceptArray, rPropCount ); + + // In eigenes Property-Array eintragen + Property& rProp = pAllPropArray[ rPropCount ]; + rProp.Name = aPropName; + rProp.Handle = rPropCount; + rProp.Type = Type( xGetRetType->getTypeClass(), xGetRetType->getName() ); + rProp.Attributes = READONLY; + + // Neuer Eintrag in die Hashtable + rPropNameMap[ aPropName ] = rPropCount; + + // Tabelle fuer XExactName pflegen + rLowerToExactNameMap[ toLower( aPropName ) ] = aPropName; + + // get-Methode merken + pAccess->checkInterfaceArraySize( pAccess->aInterfaceSeq1, + pInterfaces1, rPropCount ); + pInterfaces1[ rPropCount ] = rxMethod_i; + + // Art der Property merken + pMapTypeArray[ rPropCount ] = MAP_GETSET; + pPropertyConceptArray[ rPropCount ] = METHODS; + pAccess->mnMethodPropCount++; + + // Passende set-Methode suchen + sal_Int32 k; + for( k = 0 ; k < nSourceMethodCount ; k++ ) + { + // Methode ansprechen + const Reference<XIdlMethod>& rxMethod_k = pSourceMethods[k]; + + // Nur Methoden nehmen, die nicht schon zugeordnet sind + if( k == i || pMethodTypes[k] != STANDARD_METHOD ) + continue; + + // Name holen und auswerten + OUString aMethName2 = rxMethod_k->getName(); + OUString aStartStr2 = aMethName2.copy( 0, 3 ); + // ACHTUNG: Wegen SDL-Bug NICHT != bei OUString verwenden !!! + if( !( aStartStr2 == OUString( RTL_CONSTASCII_USTRINGPARAM("set")) ) ) + continue; + + // Ist es denn der gleiche Name? + OUString aPropName2 = aMethName2.copy( 3 ); + // ACHTUNG: Wegen SDL-Bug NICHT != bei OUString verwenden !!! + if( !( aPropName == aPropName2 ) ) + continue; + + // set-Methode muss void returnen + Reference<XIdlClass> xSetRetType = rxMethod_k->getReturnType(); + if( xSetRetType->getTypeClass() != TypeClass_VOID ) + { + continue; + } + + // set-Methode darf nur einen Parameter haben + Sequence< Reference<XIdlClass> > setParams = rxMethod_k->getParameterTypes(); + sal_Int32 nParamCount = setParams.getLength(); + if( nParamCount != 1 ) + { + continue; + } + + // Jetzt muss nur noch der return-Typ dem Parameter-Typ entsprechen + const Reference<XIdlClass>* pParamArray2 = setParams.getConstArray(); + Reference<XIdlClass> xParamType = pParamArray2[ 0 ]; + if( xParamType->equals( xGetRetType ) ) + { + pLocalMethodConcepts[ k ] = PROPERTY; + + pMethodTypes[k] = GETSET_METHOD; + + // ReadOnly-Flag wieder loschen + rProp.Attributes &= ~READONLY; + + // set-Methode merken + pAccess->checkInterfaceArraySize( pAccess->aInterfaceSeq2, + pInterfaces2, rPropCount ); + pInterfaces2[ rPropCount ] = rxMethod_k; + } + } + + // Count pflegen + rPropCount++; + } + + // Ist es eine addListener-Methode? + else if( aStartStr == OUString( RTL_CONSTASCII_USTRINGPARAM("add")) ) + { + OUString aListenerStr( RTL_CONSTASCII_USTRINGPARAM("Listener" ) ); + + // Namen der potentiellen Property + sal_Int32 nStrLen = aMethName.getLength(); + sal_Int32 nCopyLen = nStrLen - aListenerStr.getLength(); + OUString aEndStr = aMethName.copy( nCopyLen > 0 ? nCopyLen : 0 ); + + // Endet das Teil auf Listener? + // ACHTUNG: Wegen SDL-Bug NICHT != bei OUString verwenden !!! + if( !( aEndStr == aListenerStr ) ) + continue; + + // Welcher Listener? + OUString aListenerName = aMethName.copy( 3, nStrLen - aListenerStr.getLength() - 3 ); + + // TODO: Hier koennten noch genauere Pruefungen vorgenommen werden + // - Rueckgabe-Typ + // - Anzahl und Art der Parameter + + + // Passende remove-Methode suchen, sonst gilt's nicht + sal_Int32 k; + for( k = 0 ; k < nSourceMethodCount ; k++ ) + { + // Methode ansprechen + const Reference<XIdlMethod>& rxMethod_k = pSourceMethods[k]; + + // Nur Methoden nehmen, die nicht schon zugeordnet sind + if( k == i || pMethodTypes[k] != STANDARD_METHOD ) + continue; + + // Name holen und auswerten + OUString aMethName2 = rxMethod_k->getName(); + sal_Int32 nNameLen = aMethName2.getLength(); + sal_Int32 nCopyLen2 = (nNameLen < 6) ? nNameLen : 6; + OUString aStartStr2 = aMethName2.copy( 0, nCopyLen2 ); + OUString aRemoveStr( RTL_CONSTASCII_USTRINGPARAM("remove" ) ); + // ACHTUNG: Wegen SDL-Bug NICHT != bei OUString verwenden !!! + if( !( aStartStr2 == aRemoveStr ) ) + continue; + + // Ist es denn der gleiche Listener? + if( aMethName2.getLength() - aRemoveStr.getLength() <= aListenerStr.getLength() ) + continue; + OUString aListenerName2 = aMethName2.copy + ( 6, aMethName2.getLength() - aRemoveStr.getLength() - aListenerStr.getLength() ); + // ACHTUNG: Wegen SDL-Bug NICHT != bei OUString verwenden !!! + if( !( aListenerName == aListenerName2 ) ) + continue; + + // TODO: Hier koennten noch genauere Pruefungen vorgenommen werden + // - Rueckgabe-Typ + // - Anzahl und Art der Parameter + + + // Methoden sind als Listener-Schnittstelle erkannt + rMethodConcept_i |= LISTENER; + pLocalMethodConcepts[ k ] |= LISTENER; + + pMethodTypes[i] = ADD_LISTENER_METHOD; + pMethodTypes[k] = REMOVE_LISTENER_METHOD; + nListenerCount++; + } + } + } + + + // Jetzt koennen noch SET-Methoden ohne zugehoerige GET-Methode existieren, + // diese muessen zu Write-Only-Properties gemachte werden. + for( i = 0 ; i < nSourceMethodCount ; i++ ) + { + // Methode ansprechen + const Reference<XIdlMethod>& rxMethod_i = pSourceMethods[i]; + + // Nur Methoden nehmen, die nicht schon zugeordnet sind + if( pMethodTypes[i] != STANDARD_METHOD ) + continue; + + // Namen besorgen + aMethName = rxMethod_i->getName(); + + // Wenn der Name zu kurz ist, wird's sowieso nichts + if( aMethName.getLength() <= 3 ) + continue; + + // Ist es eine set-Methode ohne zugehoerige get-Methode? + aStartStr = aMethName.copy( 0, 3 ); + if( aStartStr == OUString( RTL_CONSTASCII_USTRINGPARAM("set")) ) + { + // Namen der potentiellen Property + aPropName = aMethName.copy( 3 ); + + // set-Methode muss void returnen + Reference<XIdlClass> xSetRetType = rxMethod_i->getReturnType(); + if( xSetRetType->getTypeClass() != TypeClass_VOID ) + { + continue; + } + + // set-Methode darf nur einen Parameter haben + Sequence< Reference<XIdlClass> > setParams = rxMethod_i->getParameterTypes(); + sal_Int32 nParamCount = setParams.getLength(); + if( nParamCount != 1 ) + { + continue; + } + + // Haben wir den Namen schon? + IntrospectionNameMap::iterator aIt = rPropNameMap.find( aPropName ); + if( !( aIt == rPropNameMap.end() ) ) + { + /* TODO: + OSL_TRACE( + String( "Introspection: Property \"" ) + + OOUStringToString( aPropName, CHARSET_SYSTEM ) + + String( "\" found more than once" ) ); + */ + continue; + } + + // Alles klar, es ist eine Write-Only-Property + pLocalMethodConcepts[ i ] = PROPERTY; + + pMethodTypes[i] = GETSET_METHOD; + Reference<XIdlClass> xGetRetType = setParams.getConstArray()[0]; + + // Ist die PropertySequence gross genug? + pAccess->checkPropertyArraysSize + ( pAllPropArray, pMapTypeArray, pPropertyConceptArray, rPropCount ); + + // In eigenes Property-Array eintragen + Property& rProp = pAllPropArray[ rPropCount ]; + rProp.Name = aPropName; + rProp.Handle = rPropCount; + rProp.Type = Type( xGetRetType->getTypeClass(), xGetRetType->getName() ); + rProp.Attributes = 0; // PROPERTY_WRITEONLY ??? + + // Neuer Eintrag in die Hashtable + rPropNameMap[ aPropName ] = rPropCount; + + // Tabelle fuer XExactName pflegen + rLowerToExactNameMap[ toLower( aPropName ) ] = aPropName; + + // set-Methode merken + pAccess->checkInterfaceArraySize( pAccess->aInterfaceSeq2, + pInterfaces2, rPropCount ); + pInterfaces2[ rPropCount ] = rxMethod_i; + + // Art der Property merken + pMapTypeArray[ rPropCount ] = MAP_SETONLY; + pPropertyConceptArray[ rPropCount ] = METHODS; + pAccess->mnMethodPropCount++; + + // Count pflegen + rPropCount++; + } + } + + + //******************************************************************** + + // 4. Methoden in die Gesamt-Sequence uebernehmen + + // Wieviele Methoden muessen in die Method-Sequence? + sal_Int32 nExportedMethodCount = 0; + sal_Int32 nSupportedListenerCount = 0; + for( i = 0 ; i < nSourceMethodCount ; i++ ) + { + if( pMethodTypes[ i ] != INVALID_METHOD ) + { + nExportedMethodCount++; + } + if( pMethodTypes[ i ] == ADD_LISTENER_METHOD ) + { + nSupportedListenerCount++; + } + } + + // Sequences im Access-Objekt entsprechend aufbohren + pAccess->maAllMethodSeq.realloc( nExportedMethodCount + iAllExportedMethod ); + pAccess->maMethodConceptSeq.realloc( nExportedMethodCount + iAllExportedMethod ); + pAccess->maSupportedListenerSeq.realloc( nSupportedListenerCount + iAllSupportedListener ); + + // Methoden reinschreiben + Reference<XIdlMethod>* pDestMethods = pAccess->maAllMethodSeq.getArray(); + sal_Int32* pMethodConceptArray = pAccess->maMethodConceptSeq.getArray(); + Type* pListenerClassRefs = pAccess->maSupportedListenerSeq.getArray(); + for( i = 0 ; i < nSourceMethodCount ; i++ ) + { + if( pMethodTypes[ i ] != INVALID_METHOD ) + { + // Methode ansprechen + const Reference<XIdlMethod>& rxMethod = pSourceMethods[i]; + + // Namen in Hashtable eintragen, wenn nicht schon bekannt + OUString aMethName2 = rxMethod->getName(); + IntrospectionNameMap::iterator aIt = rMethodNameMap.find( aMethName2 ); + if( aIt == rMethodNameMap.end() ) + { + // Eintragen + rMethodNameMap[ aMethName2 ] = iAllExportedMethod; + + // Tabelle fuer XExactName pflegen + rLowerToExactNameMap[ toLower( aMethName2 ) ] = aMethName2; + } + else + { + sal_Int32 iHashResult = (*aIt).second; + + Reference<XIdlMethod> xExistingMethod = pDestMethods[ iHashResult ]; + + Reference< XIdlClass > xExistingMethClass = + xExistingMethod->getDeclaringClass(); + Reference< XIdlClass > xNewMethClass = rxMethod->getDeclaringClass(); + if( xExistingMethClass->equals( xNewMethClass ) ) + continue; + } + + pDestMethods[ iAllExportedMethod ] = rxMethod; + + // Wenn kein Concept gesetzt wurde, ist die Methode "normal" + sal_Int32& rMethodConcept_i = pLocalMethodConcepts[ i ]; + if( !rMethodConcept_i ) + rMethodConcept_i = MethodConcept_NORMAL_IMPL; + pMethodConceptArray[ iAllExportedMethod ] = rMethodConcept_i; + iAllExportedMethod++; + } + if( pMethodTypes[ i ] == ADD_LISTENER_METHOD ) + { + // Klasse des Listeners ermitteln + const Reference<XIdlMethod>& rxMethod = pSourceMethods[i]; + + // void als Default-Klasse eintragen + Reference<XIdlClass> xListenerClass = TypeToIdlClass( getCppuVoidType(), m_xSMgr ); + // ALT: Reference<XIdlClass> xListenerClass = Void_getReflection()->getIdlClass(); + + // 1. Moeglichkeit: Parameter nach einer Listener-Klasse durchsuchen + // Nachteil: Superklassen muessen rekursiv durchsucht werden + Sequence< Reference<XIdlClass> > aParams = rxMethod->getParameterTypes(); + const Reference<XIdlClass>* pParamArray2 = aParams.getConstArray(); + + Reference<XIdlClass> xEventListenerClass = TypeToIdlClass( getCppuType( (Reference<XEventListener>*) NULL ), m_xSMgr ); + // ALT: Reference<XIdlClass> xEventListenerClass = XEventListener_getReflection()->getIdlClass(); + sal_Int32 nParamCount = aParams.getLength(); + sal_Int32 k; + for( k = 0 ; k < nParamCount ; k++ ) + { + const Reference<XIdlClass>& rxClass = pParamArray2[k]; + + // Sind wir von einem Listener abgeleitet? + if( rxClass->equals( xEventListenerClass ) || + isDerivedFrom( rxClass, xEventListenerClass ) ) + { + xListenerClass = rxClass; + break; + } + } + + // 2. Moeglichkeit: Namen der Methode auswerden + // Nachteil: geht nicht bei Test-Listenern, die es nicht gibt + //aMethName = rxMethod->getName(); + //aListenerName = aMethName.Copy( 3, aMethName.Len()-8-3 ); + //Reference<XIdlClass> xListenerClass = reflection->forName( aListenerName ); + Type aListenerType( TypeClass_INTERFACE, xListenerClass->getName() ); + pListenerClassRefs[ iAllSupportedListener ] = aListenerType; + iAllSupportedListener++; + } + } + + // Wenn in diesem Durchlauf XInterface-Methoden + // dabei waren, diese zukuenftig ignorieren + if( bFoundXInterface ) + bXInterfaceIsInvalid = sal_True; + + delete[] pMethodTypes; + delete[] pLocalMethodConcepts; + } + + // Super-Klasse(n) vorhanden? Dann dort fortsetzen + Sequence< Reference<XIdlClass> > aSuperClassSeq = xImplClass2->getSuperclasses(); + + // Zur Zeit wird nur von einer Superklasse ausgegangen + if( aSuperClassSeq.getLength() >= 1 ) + { + xImplClass2 = aSuperClassSeq.getConstArray()[0]; + OSL_ENSURE( xImplClass2.is(), "super class null" ); + } + else + { + xImplClass2 = NULL; + } + } + } + + // Anzahl der exportierten Methoden uebernehmen und Sequences anpassen + // (kann abweichen, weil doppelte Methoden erst nach der Ermittlung + // von nExportedMethodCount herausgeworfen werden) + sal_Int32& rMethCount = pAccess->mnMethCount; + rMethCount = iAllExportedMethod; + pAccess->maAllMethodSeq.realloc( rMethCount ); + pAccess->maMethodConceptSeq.realloc( rMethCount ); + + // Groesse der Property-Sequences anpassen + pAccess->maAllPropertySeq.realloc( rPropCount ); + pAccess->maPropertyConceptSeq.realloc( rPropCount ); + pAccess->maMapTypeSeq.realloc( rPropCount ); + + // Ende der Schleife ueber alle vom ClassProvider angegebenen Klassen + } + } + // Bei structs Fields als Properties registrieren + else //if( eType == TypeClass_STRUCT ) + { + // Ist es ein Interface oder eine struct? + //Reference<XIdlClass> xClassRef = aToInspectObj.getReflection()->getIdlClass(); + Reference<XIdlClass> xClassRef = TypeToIdlClass( aToInspectObj.getValueType(), m_xSMgr ); + if( !xClassRef.is() ) + { + OSL_ENSURE( sal_False, "Can't get XIdlClass from Reflection" ); + return pAccess; + } + + // Felder holen + Sequence< Reference<XIdlField> > fields = xClassRef->getFields(); + const Reference<XIdlField>* pFields = fields.getConstArray(); + sal_Int32 nLen = fields.getLength(); + + for( i = 0 ; i < nLen ; i++ ) + { + Reference<XIdlField> xField = pFields[i]; + Reference<XIdlClass> xPropType = xField->getType(); + OUString aPropName = xField->getName(); + + // Ist die PropertySequence gross genug? + pAccess->checkPropertyArraysSize + ( pAllPropArray, pMapTypeArray, pPropertyConceptArray, rPropCount ); + + // In eigenes Property-Array eintragen + Property& rProp = pAllPropArray[ rPropCount ]; + rProp.Name = aPropName; + rProp.Handle = rPropCount; + rProp.Type = Type( xPropType->getTypeClass(), xPropType->getName() ); + FieldAccessMode eAccessMode = xField->getAccessMode(); + rProp.Attributes = (eAccessMode == FieldAccessMode_READONLY || + eAccessMode == FieldAccessMode_CONST) + ? READONLY : 0; + + //FieldAccessMode eAccessMode = xField->getAccessMode(); + //rProp.Attributes = (eAccessMode == FieldAccessMode::READONLY || eAccessMode == CONST) + //? PropertyAttribute::READONLY : 0; + + // Namen in Hashtable eintragen + rPropNameMap[ aPropName ] = rPropCount; + + // Tabelle fuer XExactName pflegen + rLowerToExactNameMap[ toLower( aPropName ) ] = aPropName; + + // Field merken + pAccess->checkInterfaceArraySize( pAccess->aInterfaceSeq1, + pInterfaces1, rPropCount ); + pInterfaces1[ rPropCount ] = xField; + + // Art der Property merken + pMapTypeArray[ rPropCount ] = MAP_FIELD; + pPropertyConceptArray[ rPropCount ] = ATTRIBUTES; + pAccess->mnAttributePropCount++; + + // Count pflegen + rPropCount++; + } + } + + // Property-Sequence auf die richtige Laenge bringen + pAccess->maAllPropertySeq.realloc( pAccess->mnPropCount ); + + return pAccess; +} + +//************************************************************************* +Reference< XInterface > SAL_CALL ImplIntrospection_CreateInstance( const Reference< XMultiServiceFactory > & rSMgr ) + throw( RuntimeException ) +{ + Reference< XInterface > xService = (OWeakObject*)(OComponentHelper*)new ImplIntrospection( rSMgr ); + return xService; +} + +} + +extern "C" +{ +//================================================================================================== +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} +//================================================================================================== +void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * ) +{ + void * pRet = 0; + + if (pServiceManager && rtl_str_compare( pImplName, IMPLEMENTATION_NAME ) == 0) + { + Reference< XSingleServiceFactory > xFactory( createOneInstanceFactory( + reinterpret_cast< XMultiServiceFactory * >( pServiceManager ), + OUString::createFromAscii( pImplName ), + stoc_inspect::ImplIntrospection_CreateInstance, + stoc_inspect::ImplIntrospection::getSupportedServiceNames_Static() ) ); + + if (xFactory.is()) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } + + return pRet; +} +} + + diff --git a/stoc/source/inspect/makefile.mk b/stoc/source/inspect/makefile.mk new file mode 100644 index 000000000000..60864eea2496 --- /dev/null +++ b/stoc/source/inspect/makefile.mk @@ -0,0 +1,73 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME= stoc +TARGET = introspection.uno +ENABLE_EXCEPTIONS=TRUE +COMP1TYPELIST = insp + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +DLLPRE = + +# ------------------------------------------------------------------ + +.INCLUDE : ..$/cppumaker.mk + +SLOFILES= \ + $(SLO)$/introspection.obj + +SHL1TARGET= $(TARGET) + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) + +SHL1VERSIONMAP = $(SOLARENV)/src/component.map +SHL1RPATH=URELIB + +SHL1DEPN= +SHL1IMPLIB= i$(TARGET) +SHL1LIBS= $(SLB)$/$(TARGET).lib +SHL1DEF= $(MISC)$/$(SHL1TARGET).def + +DEF1NAME= $(SHL1TARGET) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +ALLTAR : $(MISC)/introspection.component + +$(MISC)/introspection.component .ERRREMOVE : \ + $(SOLARENV)/bin/createcomponent.xslt introspection.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_URE_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt introspection.component diff --git a/stoc/source/invocation/inv.xml b/stoc/source/invocation/inv.xml new file mode 100644 index 000000000000..a7b71d028f99 --- /dev/null +++ b/stoc/source/invocation/inv.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + <module-name> invocation.uno </module-name> + <component-description> + <author> Daniel Boelzle </author> + <name> com.sun.star.comp.stoc.Invocation </name> + <description> +You can construct Invocation objects through this factory service. +Invoke createInstanceWithArguments() of XSingleServiceFactory +to create an Invocation adapter for your object; +invoking createInstance() will fail. +Instances implement XInvocation to invoke methods and set/get properties at an object +which corresponds with the object which implements this interface. + +There are two ways to get information about this object. First you +can get the implemented method with XInvocation::getMethodNames() +and the properties with XInvocation::getPropertyNames(). +Second you can get, if provided, all information about the methods and the +properties with XInvocation::getIntrospection(). +Container access is available through the XIndexContainer, +XNameContainer and XEnumerationContainer +(use XInterface::queryInterface). +</description> + <loader-name> com.sun.star.loader.SharedLibrary </loader-name> + <language> C++ </language> + <status value="final"/> + <supported-service> com.sun.star.script.Invocation </supported-service> + <service-dependency>com.sun.star.script.Converter</service-dependency> + <service-dependency>com.sun.star.beans.Introspection</service-dependency> + <service-dependency>com.sun.star.reflection.CoreReflection</service-dependency> + <type> com.sun.star.script.XInvocation </type> + <type> com.sun.star.script.XInvocation2 </type> + <type> com.sun.star.script.InvocationInfo </type> + <type> com.sun.star.script.MemberType </type> + <type> com.sun.star.script.XTypeConverter </type> + <type> com.sun.star.script.FailReason </type> + <type> com.sun.star.beans.XIntrospection </type> + <type> com.sun.star.beans.XIntrospectionAccess </type> + <type> com.sun.star.beans.XPropertySet </type> + <type> com.sun.star.beans.XFastPropertySet </type> + <type> com.sun.star.beans.XMaterialHolder </type> + <type> com.sun.star.beans.XExactName </type> + <type> com.sun.star.beans.PropertyAttribute </type> + <type> com.sun.star.beans.PropertyConcept </type> + <type> com.sun.star.beans.MethodConcept </type> + <type> com.sun.star.lang.XEventListener </type> + <type> com.sun.star.lang.XInitialization </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XMultiComponentFactory </type> + <type> com.sun.star.lang.XSingleComponentFactory </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.uno.DeploymentException </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.uno.XComponentContext </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.uno.TypeClass </type> + <type> com.sun.star.container.XEnumerationAccess </type> + <type> com.sun.star.container.XNameContainer </type> + <type> com.sun.star.container.XIndexContainer </type> + <type> com.sun.star.reflection.XIdlReflection </type> + <type> com.sun.star.reflection.XIdlClassProvider </type> + <type> com.sun.star.reflection.XIdlClass </type> + <type> com.sun.star.reflection.XIdlArray </type> + <type> com.sun.star.reflection.FieldAccessMode </type> + </component-description> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> sal </project-build-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> sal3 </runtime-module-dependency> +</module-description> diff --git a/stoc/source/invocation/invocation.component b/stoc/source/invocation/invocation.component new file mode 100644 index 000000000000..67178ef2e88d --- /dev/null +++ b/stoc/source/invocation/invocation.component @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.stoc.Invocation"> + <service name="com.sun.star.script.Invocation"/> + </implementation> +</component> diff --git a/stoc/source/invocation/invocation.cxx b/stoc/source/invocation/invocation.cxx new file mode 100644 index 000000000000..f66c3af742d7 --- /dev/null +++ b/stoc/source/invocation/invocation.cxx @@ -0,0 +1,1262 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include <osl/mutex.hxx> +#include <cppuhelper/queryinterface.hxx> +#ifndef _CPPUHELER_WEAK_HXX_ +#include <cppuhelper/weak.hxx> +#endif +#include <cppuhelper/factory.hxx> +#ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX__ +#include <cppuhelper/implementationentry.hxx> +#endif +#include <cppuhelper/typeprovider.hxx> +#include <cppuhelper/implbase2.hxx> + +#include <com/sun/star/uno/DeploymentException.hpp> +#include <com/sun/star/script/FailReason.hpp> +#include <com/sun/star/script/XTypeConverter.hpp> +#include <com/sun/star/script/XInvocation.hpp> +#include <com/sun/star/script/XInvocation2.hpp> +#include <com/sun/star/reflection/XIdlReflection.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/container/XIndexContainer.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> +#include <com/sun/star/beans/XExactName.hpp> +#include <com/sun/star/beans/XMaterialHolder.hpp> +#include <com/sun/star/beans/XIntrospection.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/MethodConcept.hpp> +#include <com/sun/star/beans/PropertyConcept.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> + +#include <boost/scoped_array.hpp> +#include <rtl/ustrbuf.hxx> +#include <rtl/strbuf.hxx> + +#define SERVICENAME "com.sun.star.script.Invocation" +#define IMPLNAME "com.sun.star.comp.stoc.Invocation" + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::script; +using namespace com::sun::star::reflection; +using namespace com::sun::star::beans; +using namespace com::sun::star::registry; +using namespace com::sun::star::container; +using namespace cppu; +using namespace rtl; +using namespace osl; + + +namespace stoc_inv +{ +static rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT; + +static Sequence< OUString > inv_getSupportedServiceNames() +{ + static Sequence < OUString > *pNames = 0; + if( ! pNames ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( !pNames ) + { + static Sequence< OUString > seqNames(1); + seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME)); + pNames = &seqNames; + } + } + return *pNames; +} + +static OUString inv_getImplementationName() +{ + static OUString *pImplName = 0; + if( ! pImplName ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( ! pImplName ) + { + static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) ); + pImplName = &implName; + } + } + return *pImplName; +} + +// TODO: Zentral implementieren +inline Reference<XIdlClass> TypeToIdlClass( const Type& rType, const Reference< XIdlReflection > & xRefl ) +{ + return xRefl->forName( rType.getTypeName() ); +} + + +//================================================================================================== +class Invocation_Impl + : public OWeakObject + , public XInvocation2 + , public XNameContainer + , public XIndexContainer + , public XEnumerationAccess + , public XExactName + , public XMaterialHolder + , public XTypeProvider +{ +public: + Invocation_Impl( const Any & rAdapted, const Reference<XTypeConverter> &, + const Reference<XIntrospection> &, + const Reference<XIdlReflection> & ); + virtual ~Invocation_Impl(); + + // XInterface + virtual Any SAL_CALL queryInterface( const Type & aType) throw( RuntimeException ); + virtual void SAL_CALL acquire() throw() { OWeakObject::acquire(); } + virtual void SAL_CALL release() throw() { OWeakObject::release(); } + + + // XTypeProvider + virtual Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes( ) + throw(RuntimeException); + virtual Sequence< sal_Int8 > SAL_CALL getImplementationId( ) + throw( RuntimeException); + + // Methoden von XMaterialHolder + virtual Any SAL_CALL getMaterial(void) throw(RuntimeException); + + // ? XTool + virtual void SAL_CALL setMaterial( const Any& rMaterial ); + + // XInvocation + virtual Reference<XIntrospectionAccess> SAL_CALL getIntrospection(void) throw( RuntimeException ); + virtual Any SAL_CALL invoke(const OUString& FunctionName, const Sequence< Any >& Params, Sequence< sal_Int16 >& OutParamIndex, Sequence< Any >& OutParam) + throw( IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException ); + virtual void SAL_CALL setValue(const OUString& PropertyName, const Any& Value) + throw( UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException ); + virtual Any SAL_CALL getValue(const OUString& PropertyName) + throw( UnknownPropertyException, RuntimeException ); + virtual sal_Bool SAL_CALL hasMethod(const OUString& Name) throw( RuntimeException ); + virtual sal_Bool SAL_CALL hasProperty(const OUString& Name) throw( RuntimeException ); + + // XInvocation2 + virtual Sequence< OUString > SAL_CALL getMemberNames( ) + throw( RuntimeException ); + virtual Sequence< InvocationInfo > SAL_CALL getInfo( ) + throw( RuntimeException ); + virtual InvocationInfo SAL_CALL getInfoForName( const OUString& aName, sal_Bool bExact ) + throw( IllegalArgumentException, RuntimeException ); + + // All Access and Container methods are not thread save + // XElementAccess + virtual Type SAL_CALL getElementType(void) throw( RuntimeException ) + { return _xElementAccess->getElementType(); } + + virtual sal_Bool SAL_CALL hasElements(void) throw( RuntimeException ) + { return _xElementAccess->hasElements(); } + + // XNameContainer + virtual void SAL_CALL insertByName( const OUString& Name, const Any& Element ) + throw( IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException ) + { _xNameContainer->insertByName( Name, Element ); } + + virtual void SAL_CALL replaceByName( const OUString& Name, const Any& Element ) + throw( IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException ) + { _xNameContainer->replaceByName( Name, Element ); } + + virtual void SAL_CALL removeByName( const OUString& Name ) + throw( NoSuchElementException, WrappedTargetException, RuntimeException ) + { _xNameContainer->removeByName( Name ); } + + // XNameAccess + virtual Any SAL_CALL getByName( const OUString& Name ) + throw( NoSuchElementException, WrappedTargetException, RuntimeException ) + { return _xNameAccess->getByName( Name ); } + + virtual Sequence<OUString> SAL_CALL getElementNames(void) throw( RuntimeException ) + { return _xNameAccess->getElementNames(); } + + virtual sal_Bool SAL_CALL hasByName( const OUString& Name ) throw( RuntimeException ) + { return _xNameAccess->hasByName( Name ); } + + // XIndexContainer + virtual void SAL_CALL insertByIndex( sal_Int32 Index, const Any& Element ) + throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) + { _xIndexContainer->insertByIndex( Index, Element ); } + + virtual void SAL_CALL replaceByIndex( sal_Int32 Index, const Any& Element ) + throw( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) + { _xIndexContainer->replaceByIndex( Index, Element ); } + + virtual void SAL_CALL removeByIndex( sal_Int32 Index ) + throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) + { _xIndexContainer->removeByIndex( Index ); } + + // XIndexAccess + virtual sal_Int32 SAL_CALL getCount(void) throw( RuntimeException ) + { return _xIndexAccess->getCount(); } + + virtual Any SAL_CALL getByIndex( sal_Int32 Index ) + throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) + { return _xIndexAccess->getByIndex( Index ); } + + // XEnumerationAccess + virtual Reference<XEnumeration> SAL_CALL createEnumeration(void) throw( RuntimeException ) + { return _xEnumerationAccess->createEnumeration(); } + + // XExactName + virtual OUString SAL_CALL getExactName( const OUString& rApproximateName ) throw( RuntimeException ); + + + //===================================================================================================== +private: + void getInfoSequenceImpl( Sequence< OUString >* pStringSeq, Sequence< InvocationInfo >* pInfoSeq ); + void fillInfoForNameAccess( InvocationInfo& rInfo, const OUString& aName ); + void fillInfoForProperty( InvocationInfo& rInfo, const Property& rProp ); + void fillInfoForMethod( InvocationInfo& rInfo, const Reference< XIdlMethod > xMethod ); + + Reference<XTypeConverter> xTypeConverter; + Reference<XIntrospection> xIntrospection; + Reference<XIdlReflection> xCoreReflection; + + Any _aMaterial; + // _xDirect and (_xIntrospectionAccess, xPropertySet) are exclusive + Reference<XInvocation> _xDirect; + Reference<XInvocation2> _xDirect2; + Reference<XPropertySet> _xPropertySet; + Reference<XIntrospectionAccess> _xIntrospectionAccess; + + // supplied Interfaces + Reference<XNameContainer> _xNameContainer; + Reference<XNameAccess> _xNameAccess; + Reference<XIndexContainer> _xIndexContainer; + Reference<XIndexAccess> _xIndexAccess; + Reference<XEnumerationAccess> _xEnumerationAccess; + Reference<XElementAccess> _xElementAccess; + + // + Reference<XExactName> _xENDirect, _xENIntrospection, _xENNameAccess; +}; + + +//================================================================================================== +//================================================================================================== +//================================================================================================== + +//-------------------------------------------------------------------------------------------------- +Invocation_Impl::Invocation_Impl +( + const Any & rAdapted, + const Reference<XTypeConverter> & rTC, + const Reference<XIntrospection> & rI, + const Reference<XIdlReflection> & rCR +) + : xTypeConverter( rTC ) + , xIntrospection( rI ) + , xCoreReflection( rCR ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + setMaterial( rAdapted ); +} + +Invocation_Impl::~Invocation_Impl() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +//################################################################################################## +//### INTERFACE IMPLEMENTATIONS #################################################################### +//################################################################################################## + + +Any SAL_CALL Invocation_Impl::queryInterface( const Type & aType ) + throw( RuntimeException ) +{ + // PropertySet-Implementation + Any a = ::cppu::queryInterface( aType, + SAL_STATIC_CAST(XInvocation*, this), + SAL_STATIC_CAST(XMaterialHolder*, this), + SAL_STATIC_CAST(XTypeProvider *,this) ); + if( a.hasValue() ) + { + return a; + } + + if( aType == getCppuType( (Reference<XExactName>*) NULL ) ) + { + // Ivocation does not support XExactName, if direct object supports + // XInvocation, but not XExactName. + if ((_xDirect.is() && _xENDirect.is()) || + (!_xDirect.is() && (_xENIntrospection.is() || _xENNameAccess.is()))) + { + return makeAny( Reference< XExactName >( SAL_STATIC_CAST(XExactName*, this) ) ); + } + } + else if ( aType == getCppuType( (Reference<XNameContainer>*) NULL ) ) + { + if( _xNameContainer.is() ) + return makeAny( Reference< XNameContainer >( SAL_STATIC_CAST(XNameContainer*, this) ) ); + } + else if ( aType == getCppuType( (Reference<XNameAccess>*) NULL ) ) + { + if( _xNameAccess.is() ) + return makeAny( Reference< XNameAccess >( SAL_STATIC_CAST(XNameAccess*, this) ) ); + } + else if ( aType == getCppuType( (Reference<XIndexContainer>*) NULL ) ) + { + if (_xIndexContainer.is()) + return makeAny( Reference< XIndexContainer >( SAL_STATIC_CAST(XIndexContainer*, this) ) ); + } + else if ( aType == getCppuType( (Reference<XIndexAccess>*) NULL ) ) + { + if (_xIndexAccess.is()) + return makeAny( Reference< XIndexAccess >( SAL_STATIC_CAST(XIndexAccess*, this) ) ); + } + else if ( aType == getCppuType( (Reference<XEnumerationAccess>*) NULL ) ) + { + if (_xEnumerationAccess.is()) + return makeAny( Reference< XEnumerationAccess >( SAL_STATIC_CAST(XEnumerationAccess*, this) ) ); + } + else if ( aType == getCppuType( (Reference<XElementAccess>*) NULL ) ) + { + if (_xElementAccess.is()) + { + return makeAny( Reference< XElementAccess >( + SAL_STATIC_CAST(XElementAccess*, SAL_STATIC_CAST(XNameContainer*, this) ) ) ); + } + } + else if ( aType == getCppuType( (Reference<XInvocation2>*) NULL ) ) + { + // Invocation does not support XInvocation2, if direct object supports + // XInvocation, but not XInvocation2. + if ( ( _xDirect.is() && _xDirect2.is()) || + (!_xDirect.is() && _xIntrospectionAccess.is() ) ) + { + return makeAny( Reference< XInvocation2 >( SAL_STATIC_CAST(XInvocation2*, this) ) ); + } + } + + return OWeakObject::queryInterface( aType ); +} + + +//-------------------------------------------------------------------------------------------------- +Any Invocation_Impl::getMaterial(void) throw(RuntimeException) +{ + // AB, 12.2.1999 Sicherstellen, dass das Material wenn moeglich + // aus der direkten Invocation bzw. von der Introspection geholt + // wird, da sonst Structs nicht korrekt behandelt werden + Reference<XMaterialHolder> xMaterialHolder; + if( _xDirect.is() ) + { + xMaterialHolder = Reference<XMaterialHolder>::query( _xDirect ); + //_xDirect->queryInterface( XMaterialHolder::getSmartUik(), xMaterialHolder ); + } + else if( _xIntrospectionAccess.is() ) + { + xMaterialHolder = Reference<XMaterialHolder>::query( _xIntrospectionAccess ); + //_xIntrospectionAccess->queryInterface( XMaterialHolder::getSmartUik(), xMaterialHolder ); + } + if( xMaterialHolder.is() ) + { + return xMaterialHolder->getMaterial(); + } + return _aMaterial; +} + +//-------------------------------------------------------------------------------------------------- +void Invocation_Impl::setMaterial( const Any& rMaterial ) +{ + // set the material first and only once + Reference<XInterface> xObj; + + if (rMaterial.getValueType().getTypeClass() == TypeClass_INTERFACE) + xObj = *(Reference<XInterface>*)rMaterial.getValue(); + _aMaterial = rMaterial; + + // Ersteinmal alles ausserhalb des guards machen + _xDirect = Reference<XInvocation>::query( xObj ); + + if( _xDirect.is() ) + { + // Objekt direkt befragen + _xElementAccess = Reference<XElementAccess>::query( _xDirect ); + _xEnumerationAccess = Reference<XEnumerationAccess>::query( _xDirect ); + _xIndexAccess = Reference<XIndexAccess>::query( _xDirect ); + _xIndexContainer = Reference<XIndexContainer>::query( _xDirect ); + _xNameAccess = Reference<XNameAccess>::query( _xDirect ); + _xNameContainer = Reference<XNameContainer>::query( _xDirect ); + _xENDirect = Reference<XExactName>::query( _xDirect ); + _xDirect2 = Reference<XInvocation2>::query( _xDirect ); + + // only once!!! + //_xIntrospectionAccess = XIntrospectionAccessRef(); + //_xPropertySet = XPropertySetRef(); + } + else + { + // Invocation ueber die Introspection machen + if (xIntrospection.is()) + { + _xIntrospectionAccess = xIntrospection->inspect( _aMaterial ); + if( _xIntrospectionAccess.is() ) + { + + _xElementAccess = Reference<XElementAccess>::query( + _xIntrospectionAccess->queryAdapter( + getCppuType( (Reference<XElementAccess>*) NULL ) ) ); + + _xEnumerationAccess = Reference<XEnumerationAccess>::query( + _xIntrospectionAccess->queryAdapter( + getCppuType( (Reference<XEnumerationAccess>*) NULL )) ); + + _xIndexAccess = Reference<XIndexAccess>::query( + _xIntrospectionAccess->queryAdapter( + getCppuType( (Reference<XIndexAccess>*) NULL ) ) ); + + _xIndexContainer = Reference<XIndexContainer>::query( + _xIntrospectionAccess->queryAdapter( + getCppuType( (Reference<XIndexContainer>*) NULL ) ) ); + + _xNameAccess = Reference<XNameAccess>::query( + _xIntrospectionAccess->queryAdapter( + getCppuType( (Reference<XNameAccess>*) NULL ) ) ); + + _xNameContainer = Reference<XNameContainer>::query( + _xIntrospectionAccess->queryAdapter( + getCppuType( (Reference<XNameContainer>*) NULL ) ) ); + + _xPropertySet = Reference<XPropertySet>::query( + _xIntrospectionAccess->queryAdapter( + getCppuType( (Reference<XPropertySet>*) NULL )) ); + + _xENIntrospection = Reference<XExactName>::query( _xIntrospectionAccess ); + if (_xNameAccess.is()) + _xENNameAccess = Reference<XExactName>::query( _xNameAccess ); + } + } + /* only once !!! + _xDirect = XInvocationRef(); + if( !_xIntrospectionAccess.is() ) + { + // reset + _xElementAccess = XElementAccessRef(); + _xEnumerationAccess = XEnumerationAccessRef(); + _xIndexAccess = XIndexAccessRef(); + _xIndexContainer = XIndexContainerRef(); + _xNameAccess = XNameAccessRef(); + _xNameContainer = XNameContainerRef(); + _xPropertySet = XPropertySetRef(); + } + */ + } +} + +//-------------------------------------------------------------------------------------------------- +OUString Invocation_Impl::getExactName( const OUString& rApproximateName ) + throw( RuntimeException ) +{ + if (_xENDirect.is()) + return _xENDirect->getExactName( rApproximateName ); + + OUString aRet; + if (_xENIntrospection.is()) + aRet = _xENIntrospection->getExactName( rApproximateName ); + if (!aRet.getLength() && _xENNameAccess.is()) + aRet = _xENNameAccess->getExactName( rApproximateName ); + return aRet; +} + +//-------------------------------------------------------------------------------------------------- +Reference<XIntrospectionAccess> Invocation_Impl::getIntrospection(void) + throw( RuntimeException ) +{ + if( _xDirect.is() ) + return _xDirect->getIntrospection(); + else + return _xIntrospectionAccess; +} + +//-------------------------------------------------------------------------------------------------- +sal_Bool Invocation_Impl::hasMethod( const OUString& Name ) + throw( RuntimeException ) +{ + if (_xDirect.is()) + return _xDirect->hasMethod( Name ); + if( _xIntrospectionAccess.is() ) + return _xIntrospectionAccess->hasMethod( Name, MethodConcept::ALL ^ MethodConcept::DANGEROUS ); + return sal_False; +} + +//-------------------------------------------------------------------------------------------------- +sal_Bool Invocation_Impl::hasProperty( const OUString& Name ) + throw( RuntimeException ) +{ + if (_xDirect.is()) + return _xDirect->hasProperty( Name ); + // PropertySet + if( _xIntrospectionAccess.is() + && _xIntrospectionAccess->hasProperty( Name, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) ) + return sal_True; + // NameAccess + if( _xNameAccess.is() ) + return _xNameAccess->hasByName( Name ); + return sal_False; +} + +//-------------------------------------------------------------------------------------------------- +Any Invocation_Impl::getValue( const OUString& PropertyName ) + throw( UnknownPropertyException, RuntimeException ) +{ + if (_xDirect.is()) + return _xDirect->getValue( PropertyName ); + try + { + // PropertySet + if( _xIntrospectionAccess.is() && _xPropertySet.is() + && _xIntrospectionAccess->hasProperty + ( PropertyName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) ) + { + return _xPropertySet->getPropertyValue( PropertyName ); + } + // NameAccess + if( _xNameAccess.is() && _xNameAccess->hasByName( PropertyName ) ) + return _xNameAccess->getByName( PropertyName ); + } + catch (UnknownPropertyException &) + { + throw; + } + catch (RuntimeException &) + { + throw; + } + catch (Exception &) + { + } + + throw UnknownPropertyException( + OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get value ") ) + PropertyName, + Reference< XInterface >() ); +} + +//-------------------------------------------------------------------------------------------------- +void Invocation_Impl::setValue( const OUString& PropertyName, const Any& Value ) + throw( UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException ) +{ + if (_xDirect.is()) + _xDirect->setValue( PropertyName, Value ); + else + { + try + { + // Properties + if( _xIntrospectionAccess.is() && _xPropertySet.is() + && _xIntrospectionAccess->hasProperty( + PropertyName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) ) + { + Property aProp = _xIntrospectionAccess->getProperty( + PropertyName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ); + Reference < XIdlClass > r = TypeToIdlClass( aProp.Type, xCoreReflection ); + if( r->isAssignableFrom( TypeToIdlClass( Value.getValueType(), xCoreReflection ) ) ) + _xPropertySet->setPropertyValue( PropertyName, Value ); + else if( xTypeConverter.is() ) + _xPropertySet->setPropertyValue( + PropertyName, xTypeConverter->convertTo( Value, aProp.Type ) ); + else + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no type converter service!") ), + Reference< XInterface >() ); + } + // NameContainer + else if( _xNameContainer.is() ) + { + Any aConv; + Reference < XIdlClass > r = + TypeToIdlClass( _xNameContainer->getElementType(), xCoreReflection ); + if( r->isAssignableFrom(TypeToIdlClass( Value.getValueType(), xCoreReflection ) ) ) + aConv = Value; + else if( xTypeConverter.is() ) + aConv = xTypeConverter->convertTo( Value, _xNameContainer->getElementType() ); + else + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no type converter service!") ), + Reference< XInterface >() ); + + // bei Vorhandensein ersetzen, ansonsten einfuegen + if (_xNameContainer->hasByName( PropertyName )) + _xNameContainer->replaceByName( PropertyName, aConv ); + else + _xNameContainer->insertByName( PropertyName, aConv ); + } + else + throw UnknownPropertyException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no introspection nor name container!") ), + Reference< XInterface >() ); + } + catch (UnknownPropertyException &) + { + throw; + } + catch (CannotConvertException &) + { + throw; + } + catch (InvocationTargetException &) + { + throw; + } + catch (RuntimeException &) + { + throw; + } + catch (Exception & exc) + { + throw InvocationTargetException( + OUString( RTL_CONSTASCII_USTRINGPARAM("exception occured in setValue(): ") ) + + exc.Message, Reference< XInterface >(), makeAny( exc /* though sliced */ ) ); + } + } +} + +//-------------------------------------------------------------------------------------------------- +Any Invocation_Impl::invoke( const OUString& FunctionName, const Sequence<Any>& InParams, + Sequence<sal_Int16>& OutIndizes, Sequence<Any>& OutParams ) + throw( IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException ) +{ + if (_xDirect.is()) + return _xDirect->invoke( FunctionName, InParams, OutIndizes, OutParams ); + + if (_xIntrospectionAccess.is()) + { + // throw NoSuchMethodException if not exist + Reference<XIdlMethod> xMethod = _xIntrospectionAccess->getMethod( + FunctionName, MethodConcept::ALL ^ MethodConcept::DANGEROUS ); + + // ParameterInfos + Sequence<ParamInfo> aFParams = xMethod->getParameterInfos(); + const ParamInfo* pFParams = aFParams.getConstArray(); + sal_Int32 nFParamsLen = aFParams.getLength(); + if (nFParamsLen != InParams.getLength()) + { + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("incorrect number of parameters passed invoking function ") ) + FunctionName, + (OWeakObject *) this, (sal_Int16) 1 ); + } + + // IN Parameter + const Any* pInParams = InParams.getConstArray(); + + // Introspection Invoke Parameter + Sequence<Any> aInvokeParams( nFParamsLen ); + Any* pInvokeParams = aInvokeParams.getArray(); + + // OUT Indizes + OutIndizes.realloc( nFParamsLen ); + sal_Int16* pOutIndizes = OutIndizes.getArray(); + sal_uInt32 nOutIndex = 0; + + for ( sal_Int32 nPos = 0; nPos < nFParamsLen; ++nPos ) + { + try + { + const ParamInfo& rFParam = pFParams[nPos]; + const Reference<XIdlClass>& rDestType = rFParam.aType; + + // is IN/INOUT parameter? + if (rFParam.aMode != ParamMode_OUT) + { + if (rDestType->isAssignableFrom( TypeToIdlClass( pInParams[nPos].getValueType(), xCoreReflection ) )) + { + pInvokeParams[nPos] = pInParams[nPos]; + } + else if (xTypeConverter.is()) + { + Type aDestType( rDestType->getTypeClass(), rDestType->getName() ); + pInvokeParams[nPos] = xTypeConverter->convertTo( pInParams[nPos], aDestType ); + } + else + { + CannotConvertException aExc; + aExc.Context = *this; + aExc.Message = OUString( RTL_CONSTASCII_USTRINGPARAM("invocation type mismatch!") ); + throw aExc; + } + } + + // is OUT/INOUT parameter? + if (rFParam.aMode != ParamMode_IN) + { + pOutIndizes[nOutIndex] = (sal_Int16)nPos; + if (rFParam.aMode == ParamMode_OUT) + rDestType->createObject( pInvokeParams[nPos] ); // default init + ++nOutIndex; + } + } + catch( CannotConvertException& rExc ) + { + rExc.ArgumentIndex = nPos; // optionalen Parameter Index hinzufuegen + throw rExc; + } + } + + // execute Method + Any aRet = xMethod->invoke( _aMaterial, aInvokeParams ); + + // OUT Params + OutIndizes.realloc( nOutIndex ); + pOutIndizes = OutIndizes.getArray(); + OutParams.realloc( nOutIndex ); + Any* pOutParams = OutParams.getArray(); + + while (nOutIndex--) + { + pOutParams[nOutIndex] = pInvokeParams[ pOutIndizes[nOutIndex] ]; + } + + return aRet; + } + + RuntimeException aExc; + aExc.Context = *this; + aExc.Message = OUString( RTL_CONSTASCII_USTRINGPARAM("invocation lacking of introspection access!") ); + throw aExc; +} + +//-------------------------------------------------------------------------------------------------- + +// Struct to optimize sorting +struct MemberItem +{ + OUString aName; + + // Defines where the member comes from + enum Mode { NAMEACCESS, PROPERTYSET, METHOD } eMode; + + // Index to respective sequence + // (Index to NameAccess sequence for eMode==NAMEACCESS etc.) + sal_Int32 nIndex; +}; + +// Implementation of getting name or info +// String sequence will be filled when pStringSeq != NULL +// Info sequence will be filled when pInfoSeq != NULL +void Invocation_Impl::getInfoSequenceImpl +( + Sequence< OUString >* pStringSeq, + Sequence< InvocationInfo >* pInfoSeq +) +{ + //Sequence< OUString > aStrSeq; + //if( !pStringSeq ) + //pStringSeq = &aStrSeq; + + + // Get all needed sequences + Sequence<OUString> aNameAccessNames; + Sequence<Property> aPropertySeq; + Sequence< Reference< XIdlMethod > > aMethodSeq; + + if( _xNameAccess.is() ) + { + aNameAccessNames = _xNameAccess->getElementNames(); + } + + if( _xIntrospectionAccess.is() ) + { + aPropertySeq = _xIntrospectionAccess->getProperties + ( PropertyConcept::ALL - PropertyConcept::DANGEROUS ); + + aMethodSeq = _xIntrospectionAccess->getMethods + ( MethodConcept::ALL - MethodConcept::DANGEROUS ); + } + + sal_Int32 nNameAccessCount = aNameAccessNames.getLength(); + sal_Int32 nPropertyCount = aPropertySeq.getLength(); + sal_Int32 nMethodCount = aMethodSeq.getLength(); + sal_Int32 nTotalCount = nNameAccessCount + nPropertyCount + nMethodCount; + + // Create and fill array of MemberItems + boost::scoped_array< MemberItem > pItems( new MemberItem[ nTotalCount ] ); + const OUString* pStrings = aNameAccessNames.getConstArray(); + const Property* pProps = aPropertySeq.getConstArray(); + const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray(); + + // Fill array of MemberItems + sal_Int32 i, iTotal = 0; + + // Name Access + for( i = 0 ; i < nNameAccessCount ; i++, iTotal++ ) + { + MemberItem& rItem = pItems[ iTotal ]; + rItem.aName = pStrings[ i ]; + rItem.eMode = MemberItem::NAMEACCESS; + rItem.nIndex = i; + } + + // Property set + for( i = 0 ; i < nPropertyCount ; i++, iTotal++ ) + { + MemberItem& rItem = pItems[ iTotal ]; + rItem.aName = pProps[ i ].Name; + rItem.eMode = MemberItem::PROPERTYSET; + rItem.nIndex = i; + } + + // Methods + for( i = 0 ; i < nMethodCount ; i++, iTotal++ ) + { + MemberItem& rItem = pItems[ iTotal ]; + Reference< XIdlMethod > xMethod = pMethods[ i ]; + rItem.aName = xMethod->getName(); + rItem.eMode = MemberItem::METHOD; + rItem.nIndex = i; + } + + // Setting up result sequences + OUString* pRetStrings = NULL; + if( pStringSeq ) + { + pStringSeq->realloc( nTotalCount ); + pRetStrings = pStringSeq->getArray(); + } + + InvocationInfo* pRetInfos = NULL; + if( pInfoSeq ) + { + pInfoSeq->realloc( nTotalCount ); + pRetInfos = pInfoSeq->getArray(); + } + + // Fill result sequences in the correct order of members + for( iTotal = 0 ; iTotal < nTotalCount ; iTotal++ ) + { + MemberItem& rItem = pItems[ iTotal ]; + if( pRetStrings ) + { + pRetStrings[ iTotal ] = rItem.aName; + } + + if( pRetInfos ) + { + if( rItem.eMode == MemberItem::NAMEACCESS ) + { + fillInfoForNameAccess( pRetInfos[ iTotal ], rItem.aName ); + } + else if( rItem.eMode == MemberItem::PROPERTYSET ) + { + fillInfoForProperty( pRetInfos[ iTotal ], pProps[ rItem.nIndex ] ); + } + else if( rItem.eMode == MemberItem::METHOD ) + { + fillInfoForMethod( pRetInfos[ iTotal ], pMethods[ rItem.nIndex ] ); + } + } + } +} + +// XInvocation2 +Sequence< OUString > SAL_CALL Invocation_Impl::getMemberNames( ) + throw( RuntimeException ) +{ + if( _xDirect2.is() ) + { + return _xDirect2->getMemberNames(); + } + Sequence< OUString > aRetSeq; + getInfoSequenceImpl( &aRetSeq, NULL ); + return aRetSeq; +} + +Sequence< InvocationInfo > SAL_CALL Invocation_Impl::getInfo( ) + throw( RuntimeException ) +{ + if( _xDirect2.is() ) + { + return _xDirect2->getInfo(); + } + Sequence< InvocationInfo > aRetSeq; + getInfoSequenceImpl( NULL, &aRetSeq ); + return aRetSeq; +} + +InvocationInfo SAL_CALL Invocation_Impl::getInfoForName( const OUString& aName, sal_Bool bExact ) + throw( IllegalArgumentException, RuntimeException ) +{ + if( _xDirect2.is() ) + { + return _xDirect2->getInfoForName( aName, bExact ); + } + + sal_Bool bFound = sal_False; + OUString aExactName = aName; + InvocationInfo aRetInfo; + + if( bExact ) + aExactName = getExactName( aName ); + if( aExactName.getLength() > 0 ) + { + if( _xIntrospectionAccess->hasMethod( aExactName, MethodConcept::ALL ^ MethodConcept::DANGEROUS ) ) + { + Reference<XIdlMethod> xMethod = _xIntrospectionAccess->getMethod + ( aExactName, MethodConcept::ALL ^ MethodConcept::DANGEROUS ); + fillInfoForMethod( aRetInfo, xMethod ); + bFound = sal_True; + } + else + { + if( _xIntrospectionAccess.is() && _xIntrospectionAccess->hasProperty + ( aExactName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ) ) + { + Property aProp = _xIntrospectionAccess->getProperty + ( aExactName, PropertyConcept::ALL ^ PropertyConcept::DANGEROUS ); + fillInfoForProperty( aRetInfo, aProp ); + bFound = sal_True; + } + // NameAccess + else if( _xNameAccess.is() && _xNameAccess->hasByName( aExactName ) ) + { + fillInfoForNameAccess( aRetInfo, aExactName ); + bFound = sal_True; + } + } + } + if( !bFound ) + { + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("Unknown name, getExactName() failed!") ), + (XWeak *)(OWeakObject *)this, 0 ); + } + return aRetInfo; +} + +// Helper functions to fill InvocationInfo for XNameAccess +void Invocation_Impl::fillInfoForNameAccess +( + InvocationInfo& rInfo, + const OUString& aName +) +{ + rInfo.aName = aName; + rInfo.eMemberType = MemberType_PROPERTY; + rInfo.PropertyAttribute = 0; + if( !_xNameContainer.is() ) + { + rInfo.PropertyAttribute = PropertyAttribute::READONLY; + } + rInfo.aType = _xNameAccess->getElementType(); +} + +void Invocation_Impl::fillInfoForProperty +( + InvocationInfo& rInfo, + const Property& rProp +) +{ + rInfo.aName = rProp.Name; + rInfo.eMemberType = MemberType_PROPERTY; + rInfo.PropertyAttribute = rProp.Attributes; + rInfo.aType = rProp.Type; +} + +void Invocation_Impl::fillInfoForMethod +( + InvocationInfo& rInfo, + const Reference< XIdlMethod > xMethod +) +{ + rInfo.aName = xMethod->getName(); + rInfo.eMemberType = MemberType_METHOD; + Reference< XIdlClass > xReturnClass = xMethod->getReturnType(); + Type aReturnType( xReturnClass->getTypeClass(), xReturnClass->getName() ); + rInfo.aType = aReturnType; + Sequence<ParamInfo> aParamInfos = xMethod->getParameterInfos(); + sal_Int32 nParamCount = aParamInfos.getLength(); + if( nParamCount > 0 ) + { + const ParamInfo* pInfos = aParamInfos.getConstArray(); + + rInfo.aParamTypes.realloc( nParamCount ); + Type* pParamTypes = rInfo.aParamTypes.getArray(); + rInfo.aParamModes.realloc( nParamCount ); + ParamMode* pParamModes = rInfo.aParamModes.getArray(); + + for( sal_Int32 i = 0 ; i < nParamCount ; i++ ) + { + Reference< XIdlClass > xParamClass = pInfos[i].aType; + Type aParamType( xParamClass->getTypeClass(), xParamClass->getName() ); + pParamTypes[ i ] = aParamType; + pParamModes[ i ] = pInfos[i].aMode; + } + } +} + + +// XTypeProvider +Sequence< Type > SAL_CALL Invocation_Impl::getTypes(void) throw( RuntimeException ) +{ + static Sequence< Type > const * s_pTypes = 0; + if (! s_pTypes) + { + Sequence< Type > types( 4 +8 ); + Type * pTypes = types.getArray(); + sal_Int32 n = 0; + + pTypes[ n++ ] = ::getCppuType( (Reference< XTypeProvider > const *)0 ); + pTypes[ n++ ] = ::getCppuType( (Reference< XWeak > const *)0 ); + pTypes[ n++ ] = ::getCppuType( (Reference< XInvocation > const *)0 ); + pTypes[ n++ ] = ::getCppuType( (Reference< XMaterialHolder > const *)0 ); + + // Ivocation does not support XExactName, if direct object supports + // XInvocation, but not XExactName. + if ((_xDirect.is() && _xENDirect.is()) || + (!_xDirect.is() && (_xENIntrospection.is() || _xENNameAccess.is()))) + { + pTypes[ n++ ] = ::getCppuType( (Reference< XExactName > const *)0 ); + } + if( _xNameContainer.is() ) + { + pTypes[ n++ ] = ::getCppuType( (Reference< XNameContainer > const *)0 ); + } + if( _xNameAccess.is() ) + { + pTypes[ n++ ] = ::getCppuType( (Reference< XNameAccess > const *)0 ); + } + if (_xIndexContainer.is()) + { + pTypes[ n++ ] = ::getCppuType( (Reference< XIndexContainer > const *)0 ); + } + if (_xIndexAccess.is()) + { + pTypes[ n++ ] = ::getCppuType( (Reference< XIndexAccess > const *)0 ); + } + if (_xEnumerationAccess.is()) + { + pTypes[ n++ ] = ::getCppuType( (Reference< XEnumerationAccess > const *)0 ); + } + if (_xElementAccess.is()) + { + pTypes[ n++ ] = ::getCppuType( (Reference< XElementAccess > const *)0 ); + } + // Invocation does not support XInvocation2, if direct object supports + // XInvocation, but not XInvocation2. + if ( ( _xDirect.is() && _xDirect2.is()) || + (!_xDirect.is() && _xIntrospectionAccess.is() ) ) + { + pTypes[ n++ ] = ::getCppuType( (Reference< XInvocation2 > const *)0 ); + } + + types.realloc( n ); + + // store types + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_pTypes) + { + static Sequence< Type > s_types( types ); + s_pTypes = &s_types; + } + } + return *s_pTypes; +} + +Sequence< sal_Int8 > SAL_CALL Invocation_Impl::getImplementationId( ) throw( RuntimeException) +{ + static OImplementationId *pId = 0; + if( ! pId ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( ! pId ) + { + static OImplementationId id( sal_False ); + pId = &id; + } + } + return pId->getImplementationId(); +} + +//================================================================================================== +//================================================================================================== +//================================================================================================== +class InvocationService + : public WeakImplHelper2< XSingleServiceFactory, XServiceInfo > +{ +public: + InvocationService( const Reference<XComponentContext> & xCtx ); + virtual ~InvocationService(); + + // XServiceInfo + OUString SAL_CALL getImplementationName() throw( RuntimeException ); + sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw( RuntimeException ); + Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw( RuntimeException ); + + // XSingleServiceFactory + Reference<XInterface> SAL_CALL createInstance(void) throw( Exception, RuntimeException ); + Reference<XInterface> SAL_CALL createInstanceWithArguments( + const Sequence<Any>& rArguments ) throw( Exception, RuntimeException ); +private: + Reference<XComponentContext> mxCtx; + Reference<XMultiComponentFactory> mxSMgr; + Reference<XTypeConverter> xTypeConverter; + Reference<XIntrospection> xIntrospection; + Reference<XIdlReflection> xCoreReflection; +}; + +InvocationService::InvocationService( const Reference<XComponentContext> & xCtx ) + : mxCtx( xCtx ) + , mxSMgr( xCtx->getServiceManager() ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + xTypeConverter = Reference<XTypeConverter>( + mxSMgr->createInstanceWithContext( + OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.script.Converter")), + xCtx ), + UNO_QUERY ); + xIntrospection = Reference<XIntrospection>( + mxSMgr->createInstanceWithContext( + OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.beans.Introspection")), + xCtx), + UNO_QUERY); + mxCtx->getValueByName( + OUString( + RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theCoreReflection")) ) + >>= xCoreReflection; + OSL_ENSURE( xCoreReflection.is(), "### CoreReflection singleton not accessable!?" ); + if (! xCoreReflection.is()) + { + throw DeploymentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theCoreReflection singleton not accessable") ), + Reference< XInterface >() ); + } +// xCoreReflection = Reference<XIdlReflection>( +// mxSMgr->createInstanceWithContext( +// OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.reflection.CoreReflection")), +// xCtx), +// UNO_QUERY); +} + +InvocationService::~InvocationService() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +// XServiceInfo +OUString InvocationService::getImplementationName() throw( RuntimeException ) +{ + return inv_getImplementationName(); +} + +// XServiceInfo +sal_Bool InvocationService::supportsService(const OUString& ServiceName) throw( RuntimeException ) +{ + Sequence< OUString > aSNL = getSupportedServiceNames(); + const OUString * pArray = aSNL.getConstArray(); + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return sal_True; + return sal_False; +} + +// XServiceInfo +Sequence< OUString > InvocationService::getSupportedServiceNames(void) throw( RuntimeException ) +{ + return inv_getSupportedServiceNames(); +} + +//-------------------------------------------------------------------------------------------------- +Reference<XInterface> InvocationService::createInstance(void) throw( Exception, RuntimeException ) +{ + //TODO:throw( Exception(OUString( RTL_CONSTASCII_USTRINGPARAM("no default construction of invocation adapter possible!")), *this) ); + return Reference<XInterface>(); // dummy +} + +//-------------------------------------------------------------------------------------------------- +Reference<XInterface> InvocationService::createInstanceWithArguments( + const Sequence<Any>& rArguments ) throw( Exception, RuntimeException ) +{ + if (rArguments.getLength() == 1) + { + return Reference< XInterface > + ( *new Invocation_Impl( *rArguments.getConstArray(), + xTypeConverter, xIntrospection, xCoreReflection ) ); + } + else + { + //TODO:throw( Exception(OUString( RTL_CONSTASCII_USTRINGPARAM("no default construction of invocation adapter possible!")), *this) ); + return Reference<XInterface>(); + } +} + + +//************************************************************************* +Reference<XInterface> SAL_CALL InvocationService_CreateInstance( const Reference<XComponentContext> & xCtx ) + throw( RuntimeException ) +{ + Reference<XInterface> xService = Reference< XInterface > ( *new InvocationService( xCtx ) ); + return xService; +} + +} + +using namespace stoc_inv; +static struct ImplementationEntry g_entries[] = +{ + { + InvocationService_CreateInstance, inv_getImplementationName, + inv_getSupportedServiceNames, createSingleComponentFactory, + &g_moduleCount.modCnt , 0 + }, + { 0, 0, 0, 0, 0, 0 } +}; + +extern "C" +{ +sal_Bool SAL_CALL component_canUnload( TimeValue *pTime ) +{ + return g_moduleCount.canUnload( &g_moduleCount , pTime ); +} + +//================================================================================================== +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} +//================================================================================================== +void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) +{ + return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries ); +} +} + + + diff --git a/stoc/source/invocation/makefile.mk b/stoc/source/invocation/makefile.mk new file mode 100644 index 000000000000..72eeea37c659 --- /dev/null +++ b/stoc/source/invocation/makefile.mk @@ -0,0 +1,71 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME= stoc +TARGET = invocation.uno +ENABLE_EXCEPTIONS=TRUE +COMP1TYPELIST = inv + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +DLLPRE = + +# ------------------------------------------------------------------ + +.INCLUDE : ..$/cppumaker.mk + +SLOFILES= \ + $(SLO)$/invocation.obj + +SHL1TARGET= $(TARGET) + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) + +SHL1VERSIONMAP = $(SOLARENV)/src/unloadablecomponent.map +SHL1DEPN= +SHL1IMPLIB= i$(TARGET) +SHL1LIBS= $(SLB)$/$(TARGET).lib +SHL1RPATH=URELIB + +DEF1NAME= $(SHL1TARGET) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +ALLTAR : $(MISC)/invocation.component + +$(MISC)/invocation.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + invocation.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_URE_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt invocation.component diff --git a/stoc/source/invocation_adapterfactory/iafactory.cxx b/stoc/source/invocation_adapterfactory/iafactory.cxx new file mode 100644 index 000000000000..70d2562657ad --- /dev/null +++ b/stoc/source/invocation_adapterfactory/iafactory.cxx @@ -0,0 +1,1025 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include <hash_map> +#include <hash_set> + +#include <osl/diagnose.h> +#include <osl/interlck.h> +#include <osl/mutex.hxx> + +#include <uno/dispatcher.h> +#include <uno/data.h> +#include <uno/any2.h> +#include <uno/mapping.hxx> + +#include <cppuhelper/factory.hxx> +#include <cppuhelper/implbase3.hxx> +#include <cppuhelper/implementationentry.hxx> + +#include <com/sun/star/uno/XAggregation.hpp> +#include <com/sun/star/script/XTypeConverter.hpp> +#include <com/sun/star/script/XInvocationAdapterFactory.hpp> +#include <com/sun/star/script/XInvocationAdapterFactory2.hpp> +#include <com/sun/star/script/XInvocation.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/registry/XSimpleRegistry.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/reflection/InvocationTargetException.hpp> +#include "com/sun/star/uno/RuntimeException.hpp" + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + +#define SERVICENAME "com.sun.star.script.InvocationAdapterFactory" +#define IMPLNAME "com.sun.star.comp.stoc.InvocationAdapterFactory" + + +using namespace ::std; +using namespace ::rtl; +using namespace ::osl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +namespace stoc_invadp +{ + +static rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT; + +static Sequence< OUString > invadp_getSupportedServiceNames() +{ + static Sequence < OUString > *pNames = 0; + if( ! pNames ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( !pNames ) + { + static Sequence< OUString > seqNames(1); + seqNames.getArray()[0] = + OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME)); + pNames = &seqNames; + } + } + return *pNames; +} + +static OUString invadp_getImplementationName() +{ + static OUString *pImplName = 0; + if( ! pImplName ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( ! pImplName ) + { + static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) ); + pImplName = &implName; + } + } + return *pImplName; +} + +struct hash_ptr +{ + inline size_t operator() ( void * p ) const + { return (size_t)p; } +}; +typedef hash_set< void *, hash_ptr, equal_to< void * > > t_ptr_set; +typedef hash_map< void *, t_ptr_set, hash_ptr, equal_to< void * > > t_ptr_map; + +//============================================================================== +class FactoryImpl + : public ::cppu::WeakImplHelper3< lang::XServiceInfo, + script::XInvocationAdapterFactory, + script::XInvocationAdapterFactory2 > +{ +public: + Mapping m_aUno2Cpp; + Mapping m_aCpp2Uno; + uno_Interface * m_pConverter; + + typelib_TypeDescription * m_pInvokMethodTD; + typelib_TypeDescription * m_pSetValueTD; + typelib_TypeDescription * m_pGetValueTD; + typelib_TypeDescription * m_pAnySeqTD; + typelib_TypeDescription * m_pShortSeqTD; + typelib_TypeDescription * m_pConvertToTD; + + Mutex m_mutex; + t_ptr_map m_receiver2adapters; + + FactoryImpl( Reference< XComponentContext > const & xContext ) + SAL_THROW( (RuntimeException) ); + virtual ~FactoryImpl() SAL_THROW( () ); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() + throw (RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) + throw (RuntimeException); + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() + throw (RuntimeException); + + // XInvocationAdapterFactory + virtual Reference< XInterface > SAL_CALL createAdapter( + const Reference< script::XInvocation > & xReceiver, const Type & rType ) + throw (RuntimeException); + // XInvocationAdapterFactory2 + virtual Reference< XInterface > SAL_CALL createAdapter( + const Reference< script::XInvocation > & xReceiver, + const Sequence< Type > & rTypes ) + throw (RuntimeException); +}; +struct AdapterImpl; +//============================================================================== +struct InterfaceAdapterImpl : public uno_Interface +{ + AdapterImpl * m_pAdapter; + typelib_InterfaceTypeDescription * m_pTypeDescr; +}; +//============================================================================== +struct AdapterImpl +{ + oslInterlockedCount m_nRef; + FactoryImpl * m_pFactory; + void * m_key; // map key + uno_Interface * m_pReceiver; // XInvocation receiver + + sal_Int32 m_nInterfaces; + InterfaceAdapterImpl * m_pInterfaces; + + // XInvocation calls + void getValue( + const typelib_TypeDescription * pMemberType, + void * pReturn, void * pArgs[], uno_Any ** ppException ); + void setValue( + const typelib_TypeDescription * pMemberType, + void * pReturn, void * pArgs[], uno_Any ** ppException ); + void invoke( + const typelib_TypeDescription * pMemberType, + void * pReturn, void * pArgs[], uno_Any ** ppException ); + + bool coerce_assign( + void * pDest, typelib_TypeDescriptionReference * pType, + uno_Any * pSource, uno_Any * pExc ); + inline bool coerce_construct( + void * pDest, typelib_TypeDescriptionReference * pType, + uno_Any * pSource, uno_Any * pExc ); + + inline void acquire() + SAL_THROW( () ); + inline void release() + SAL_THROW( () ); + inline ~AdapterImpl() + SAL_THROW( () ); + inline AdapterImpl( + void * key, Reference< script::XInvocation > const & xReceiver, + const Sequence< Type > & rTypes, + FactoryImpl * pFactory ) + SAL_THROW( (RuntimeException) ); +}; +//______________________________________________________________________________ +inline AdapterImpl::~AdapterImpl() + SAL_THROW( () ) +{ + for ( sal_Int32 nPos = m_nInterfaces; nPos--; ) + { + ::typelib_typedescription_release( + (typelib_TypeDescription *)m_pInterfaces[ nPos ].m_pTypeDescr ); + } + delete [] m_pInterfaces; + // + (*m_pReceiver->release)( m_pReceiver ); + m_pFactory->release(); +} +//______________________________________________________________________________ +inline void AdapterImpl::acquire() + SAL_THROW( () ) +{ + ::osl_incrementInterlockedCount( &m_nRef ); +} +//______________________________________________________________________________ +inline void AdapterImpl::release() + SAL_THROW( () ) +{ + bool delete_this = false; + { + MutexGuard guard( m_pFactory->m_mutex ); + if (! ::osl_decrementInterlockedCount( &m_nRef )) + { + t_ptr_map::iterator iFind( + m_pFactory->m_receiver2adapters.find( m_key ) ); + OSL_ASSERT( m_pFactory->m_receiver2adapters.end() != iFind ); + t_ptr_set & adapter_set = iFind->second; + if (adapter_set.erase( this ) != 1) { + OSL_ASSERT( false ); + } + if (adapter_set.empty()) + { + m_pFactory->m_receiver2adapters.erase( iFind ); + } + delete_this = true; + } + } + if (delete_this) + delete this; +} + +//------------------------------------------------------------------------------ +static inline void constructRuntimeException( + uno_Any * pExc, const OUString & rMsg ) +{ + RuntimeException exc( rMsg, Reference< XInterface >() ); + // no conversion neeeded due to binary compatibility + no convertable type + ::uno_type_any_construct( + pExc, &exc, ::getCppuType( &exc ).getTypeLibType(), 0 ); +} + +//------------------------------------------------------------------------------ +static inline sal_Bool type_equals( + typelib_TypeDescriptionReference * pType1, + typelib_TypeDescriptionReference * pType2 ) + SAL_THROW( () ) +{ + return (pType1 == pType2 || + (pType1->pTypeName->length == pType2->pTypeName->length && + 0 == ::rtl_ustr_compare( + pType1->pTypeName->buffer, pType2->pTypeName->buffer ))); +} + +//______________________________________________________________________________ +bool AdapterImpl::coerce_assign( + void * pDest, typelib_TypeDescriptionReference * pType, uno_Any * pSource, + uno_Any * pOutExc ) +{ + if (typelib_TypeClass_ANY == pType->eTypeClass) + { + ::uno_type_any_assign( + (uno_Any *)pDest, pSource->pData, pSource->pType, 0, 0 ); + return true; + } + if (::uno_type_assignData( + pDest, pType, pSource->pData, pSource->pType, 0, 0, 0 )) + { + return true; + } + else // try type converter + { + uno_Any ret; + void * args[ 2 ]; + args[ 0 ] = pSource; + args[ 1 ] = &pType; + uno_Any exc; + uno_Any * p_exc = &exc; + + // converTo() + (*m_pFactory->m_pConverter->pDispatcher)( + m_pFactory->m_pConverter, + m_pFactory->m_pConvertToTD, &ret, args, &p_exc ); + + if (p_exc) // exception occured + { + OSL_ASSERT( + p_exc->pType->eTypeClass == typelib_TypeClass_EXCEPTION ); + if (typelib_typedescriptionreference_isAssignableFrom( + ::getCppuType( + (RuntimeException const *) 0 ).getTypeLibType(), + p_exc->pType )) + { + // is RuntimeException or derived: rethrow + uno_type_any_construct( + pOutExc, p_exc->pData, p_exc->pType, 0 ); + } + else + { + // set runtime exception + constructRuntimeException( + pOutExc, OUSTR("type coercion failed: ") + + reinterpret_cast< Exception const * >( + p_exc->pData )->Message ); + } + ::uno_any_destruct( p_exc, 0 ); + // pOutExc constructed + return false; + } + else + { + bool succ = (sal_False != ::uno_type_assignData( + pDest, pType, ret.pData, ret.pType, 0, 0, 0 )); + ::uno_any_destruct( &ret, 0 ); + OSL_ENSURE( + succ, "### conversion succeeded, but assignment failed!?" ); + if (! succ) + { + // set runtime exception + constructRuntimeException( + pOutExc, + OUSTR("type coercion failed: " + "conversion succeeded, but assignment failed?!") ); + } + return succ; + } + } +} +//______________________________________________________________________________ +inline bool AdapterImpl::coerce_construct( + void * pDest, typelib_TypeDescriptionReference * pType, uno_Any * pSource, + uno_Any * pExc ) +{ + if (typelib_TypeClass_ANY == pType->eTypeClass) + { + ::uno_type_copyData( pDest, pSource, pType, 0 ); + return true; + } + if (type_equals( pType, pSource->pType)) + { + ::uno_type_copyData( pDest, pSource->pData, pType, 0 ); + return true; + } + ::uno_type_constructData( pDest, pType ); + return coerce_assign( pDest, pType, pSource, pExc ); +} + +//------------------------------------------------------------------------------ +static void handleInvokExc( uno_Any * pDest, uno_Any * pSource ) +{ + OUString const & name = + *reinterpret_cast< OUString const * >( &pSource->pType->pTypeName ); + + if (name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( + "com.sun.star.reflection.InvocationTargetException") )) + { + // unwrap invocation target exception + uno_Any * target_exc = + &reinterpret_cast< reflection::InvocationTargetException * >( + pSource->pData )->TargetException; + ::uno_type_any_construct( + pDest, target_exc->pData, target_exc->pType, 0 ); + } + else // all other exceptions are wrapped to RuntimeException + { + if (typelib_TypeClass_EXCEPTION == pSource->pType->eTypeClass) + { + constructRuntimeException( + pDest, ((Exception const *)pSource->pData)->Message ); + } + else + { + constructRuntimeException( + pDest, OUSTR("no exception has been thrown via invocation?!") ); + } + } +} +//______________________________________________________________________________ +void AdapterImpl::getValue( + const typelib_TypeDescription * pMemberType, + void * pReturn, void * [], uno_Any ** ppException ) +{ + uno_Any aInvokRet; + void * pInvokArgs[1]; + pInvokArgs[0] = + &((typelib_InterfaceMemberTypeDescription *)pMemberType)->pMemberName; + uno_Any aInvokExc; + uno_Any * pInvokExc = &aInvokExc; + + // getValue() + (*m_pReceiver->pDispatcher)( + m_pReceiver, m_pFactory->m_pGetValueTD, + &aInvokRet, pInvokArgs, &pInvokExc ); + + if (pInvokExc) // getValue() call exception + { + handleInvokExc( *ppException, pInvokExc ); + ::uno_any_destruct( pInvokExc, 0 ); // cleanup + } + else // invocation call succeeded + { + if (coerce_construct( + pReturn, + ((typelib_InterfaceAttributeTypeDescription *) + pMemberType)->pAttributeTypeRef, + &aInvokRet, *ppException )) + { + *ppException = 0; // no exceptions be thrown + } + ::uno_any_destruct( &aInvokRet, 0 ); + } +} +//______________________________________________________________________________ +void AdapterImpl::setValue( + const typelib_TypeDescription * pMemberType, + void *, void * pArgs[], uno_Any ** ppException ) +{ + uno_Any aInvokVal; + ::uno_type_any_construct( + &aInvokVal, pArgs[0], + ((typelib_InterfaceAttributeTypeDescription *) + pMemberType)->pAttributeTypeRef, 0 ); + + void * pInvokArgs[2]; + pInvokArgs[0] = + &((typelib_InterfaceMemberTypeDescription *)pMemberType)->pMemberName; + pInvokArgs[1] = &aInvokVal; + uno_Any aInvokExc; + uno_Any * pInvokExc = &aInvokExc; + + // setValue() + (*m_pReceiver->pDispatcher)( + m_pReceiver, m_pFactory->m_pSetValueTD, 0, pInvokArgs, &pInvokExc ); + + if (pInvokExc) // setValue() call exception + { + handleInvokExc( *ppException, pInvokExc ); + ::uno_any_destruct( pInvokExc, 0 ); // cleanup + } + else // invocation call succeeded + { + *ppException = 0; // no exceptions be thrown + } + + ::uno_any_destruct( &aInvokVal, 0 ); // cleanup +} +//______________________________________________________________________________ +void AdapterImpl::invoke( + const typelib_TypeDescription * pMemberType, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + sal_Int32 nParams = + ((typelib_InterfaceMethodTypeDescription *)pMemberType)->nParams; + typelib_MethodParameter * pFormalParams = + ((typelib_InterfaceMethodTypeDescription *)pMemberType)->pParams; + + // in params + uno_Sequence * pInParamsSeq = 0; + ::uno_sequence_construct( + &pInParamsSeq, m_pFactory->m_pAnySeqTD, 0, nParams, 0 ); + uno_Any * pInAnys = (uno_Any *)pInParamsSeq->elements; + sal_Int32 nOutParams = 0; + sal_Int32 nPos; + for ( nPos = nParams; nPos--; ) + { + typelib_MethodParameter const & rParam = pFormalParams[nPos]; + if (rParam.bIn) // is in/inout param + { + ::uno_type_any_assign( + &pInAnys[nPos], pArgs[nPos], rParam.pTypeRef, 0, 0 ); + } + // else: pure out is empty any + + if (rParam.bOut) + ++nOutParams; + } + + // out params, out indices + uno_Sequence * pOutIndices; + uno_Sequence * pOutParams; + // return value + uno_Any aInvokRet; + // perform call + void * pInvokArgs[4]; + pInvokArgs[0] = + &((typelib_InterfaceMemberTypeDescription *)pMemberType)->pMemberName; + pInvokArgs[1] = &pInParamsSeq; + pInvokArgs[2] = &pOutIndices; + pInvokArgs[3] = &pOutParams; + uno_Any aInvokExc; + uno_Any * pInvokExc = &aInvokExc; + + // invoke() call + (*m_pReceiver->pDispatcher)( + m_pReceiver, m_pFactory->m_pInvokMethodTD, + &aInvokRet, pInvokArgs, &pInvokExc ); + + if (pInvokExc) + { + handleInvokExc( *ppException, pInvokExc ); + ::uno_any_destruct( pInvokExc, 0 ); // cleanup + } + else // no invocation exception + { + // write changed out params + OSL_ENSURE( + pOutParams->nElements == nOutParams && + pOutIndices->nElements == nOutParams, + "### out params lens differ!" ); + if (pOutParams->nElements == nOutParams && + pOutIndices->nElements == nOutParams) + { + sal_Int16 * pIndices = (sal_Int16 *)pOutIndices->elements; + uno_Any * pOut = (uno_Any *)pOutParams->elements; + for ( nPos = 0; nPos < nOutParams; ++nPos ) + { + sal_Int32 nIndex = pIndices[nPos]; + OSL_ENSURE( nIndex < nParams, "### illegal index!" ); + typelib_MethodParameter const & rParam = pFormalParams[nIndex]; + bool succ; + if (rParam.bIn) // is in/inout param + { + succ = coerce_assign( + pArgs[nIndex], rParam.pTypeRef, &pOut[nPos], + *ppException ); + } + else // pure out + { + succ = coerce_construct( + pArgs[nIndex], rParam.pTypeRef, &pOut[nPos], + *ppException ); + } + if (! succ) // cleanup of out params + { + for ( sal_Int32 n = 0; n <= nPos; ++n ) + { + sal_Int32 nIndex2 = pIndices[n]; + OSL_ENSURE( nIndex2 < nParams, "### illegal index!" ); + typelib_MethodParameter const & rParam2 = + pFormalParams[nIndex2]; + if (! rParam2.bIn) // is pure out param + { + ::uno_type_destructData( + pArgs[nIndex2], rParam2.pTypeRef, 0 ); + } + } + } + } + if (nPos == pOutIndices->nElements) + { + // out param copy ok; write return value + if (coerce_construct( + pReturn, + ((typelib_InterfaceMethodTypeDescription *) + pMemberType)->pReturnTypeRef, + &aInvokRet, *ppException )) + { + *ppException = 0; // no exception + } + } + } + else + { + // set runtime exception + constructRuntimeException( + *ppException, + OUSTR("out params lengths differ after invocation call!") ); + } + // cleanup invok out params + ::uno_destructData( &pOutIndices, m_pFactory->m_pShortSeqTD, 0 ); + ::uno_destructData( &pOutParams, m_pFactory->m_pAnySeqTD, 0 ); + // cleanup invok return value + ::uno_any_destruct( &aInvokRet, 0 ); + } + // cleanup constructed in params + ::uno_destructData( &pInParamsSeq, m_pFactory->m_pAnySeqTD, 0 ); +} + +extern "C" +{ +//______________________________________________________________________________ +static void SAL_CALL adapter_acquire( uno_Interface * pUnoI ) +{ + static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->acquire(); +} +//______________________________________________________________________________ +static void SAL_CALL adapter_release( uno_Interface * pUnoI ) +{ + static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter->release(); +} +//______________________________________________________________________________ +static void SAL_CALL adapter_dispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberType, + void * pReturn, void * pArgs[], uno_Any ** ppException ) +{ + // query to emulated interface + switch (((typelib_InterfaceMemberTypeDescription *)pMemberType)->nPosition) + { + case 0: // queryInterface() + { + AdapterImpl * that = + static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter; + *ppException = 0; // no exc + typelib_TypeDescriptionReference * pDemanded = + *(typelib_TypeDescriptionReference **)pArgs[0]; + // pInterfaces[0] is XInterface + for ( sal_Int32 nPos = 0; nPos < that->m_nInterfaces; ++nPos ) + { + typelib_InterfaceTypeDescription * pTD = + that->m_pInterfaces[nPos].m_pTypeDescr; + while (pTD) + { + if (type_equals( + ((typelib_TypeDescription *)pTD)->pWeakRef, pDemanded )) + { + uno_Interface * pUnoI2 = &that->m_pInterfaces[nPos]; + ::uno_any_construct( + (uno_Any *)pReturn, &pUnoI2, + (typelib_TypeDescription *)pTD, 0 ); + return; + } + pTD = pTD->pBaseTypeDescription; + } + } + ::uno_any_construct( (uno_Any *)pReturn, 0, 0, 0 ); // clear() + break; + } + case 1: // acquire() + *ppException = 0; // no exc + adapter_acquire( pUnoI ); + break; + case 2: // release() + *ppException = 0; // no exc + adapter_release( pUnoI ); + break; + + default: + { + AdapterImpl * that = + static_cast< InterfaceAdapterImpl * >( pUnoI )->m_pAdapter; + if (pMemberType->eTypeClass == typelib_TypeClass_INTERFACE_METHOD) + { + that->invoke( pMemberType, pReturn, pArgs, ppException ); + } + else // attribute + { + if (pReturn) + that->getValue( pMemberType, pReturn, pArgs, ppException ); + else + that->setValue( pMemberType, pReturn, pArgs, ppException ); + } + } + } +} +} +//______________________________________________________________________________ +AdapterImpl::AdapterImpl( + void * key, Reference< script::XInvocation > const & xReceiver, + const Sequence< Type > & rTypes, + FactoryImpl * pFactory ) + SAL_THROW( (RuntimeException) ) + : m_nRef( 1 ), + m_pFactory( pFactory ), + m_key( key ) +{ + // init adapters + m_nInterfaces = rTypes.getLength(); + m_pInterfaces = new InterfaceAdapterImpl[ rTypes.getLength() ]; + const Type * pTypes = rTypes.getConstArray(); + for ( sal_Int32 nPos = rTypes.getLength(); nPos--; ) + { + InterfaceAdapterImpl * pInterface = &m_pInterfaces[nPos]; + pInterface->acquire = adapter_acquire; + pInterface->release = adapter_release; + pInterface->pDispatcher = adapter_dispatch; + pInterface->m_pAdapter = this; + pInterface->m_pTypeDescr = 0; + pTypes[nPos].getDescription( + (typelib_TypeDescription **)&pInterface->m_pTypeDescr ); + OSL_ASSERT( pInterface->m_pTypeDescr ); + if (! pInterface->m_pTypeDescr) + { + for ( sal_Int32 n = 0; n < nPos; ++n ) + { + ::typelib_typedescription_release( + (typelib_TypeDescription *) + m_pInterfaces[ n ].m_pTypeDescr ); + } + delete [] m_pInterfaces; + throw RuntimeException( + OUSTR("cannot retrieve all interface type infos!"), + Reference< XInterface >() ); + } + } + + // map receiver + m_pReceiver = (uno_Interface *)m_pFactory->m_aCpp2Uno.mapInterface( + xReceiver.get(), ::getCppuType( &xReceiver ) ); + OSL_ASSERT( 0 != m_pReceiver ); + if (! m_pReceiver) + { + throw RuntimeException( + OUSTR("cannot map receiver!"), Reference< XInterface >() ); + } + + m_pFactory->acquire(); +} + +//______________________________________________________________________________ +FactoryImpl::FactoryImpl( Reference< XComponentContext > const & xContext ) + SAL_THROW( (RuntimeException) ) + : m_pInvokMethodTD( 0 ), + m_pSetValueTD( 0 ), + m_pGetValueTD( 0 ), + m_pAnySeqTD( 0 ), + m_pShortSeqTD( 0 ), + m_pConvertToTD( 0 ) +{ + // C++/UNO bridge + OUString aCppEnvTypeName = OUSTR(CPPU_CURRENT_LANGUAGE_BINDING_NAME); + OUString aUnoEnvTypeName = OUSTR(UNO_LB_UNO); + m_aUno2Cpp = Mapping( aUnoEnvTypeName, aCppEnvTypeName ); + m_aCpp2Uno = Mapping( aCppEnvTypeName, aUnoEnvTypeName ); + OSL_ENSURE( + m_aUno2Cpp.is() && m_aCpp2Uno.is(), "### no uno / C++ mappings!" ); + + // type converter + Reference< script::XTypeConverter > xConverter( + xContext->getServiceManager()->createInstanceWithContext( + OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.script.Converter") ), + xContext ), + UNO_QUERY_THROW ); + m_pConverter = (uno_Interface *)m_aCpp2Uno.mapInterface( + xConverter.get(), ::getCppuType( &xConverter ) ); + OSL_ASSERT( 0 != m_pConverter ); + + // some type info: + // sequence< any > + Type const & rAnySeqType = ::getCppuType( (const Sequence< Any > *)0 ); + rAnySeqType.getDescription( &m_pAnySeqTD ); + // sequence< short > + const Type & rShortSeqType = + ::getCppuType( (const Sequence< sal_Int16 > *)0 ); + rShortSeqType.getDescription( &m_pShortSeqTD ); + // script.XInvocation + typelib_TypeDescription * pTD = 0; + const Type & rInvType = ::getCppuType( + (const Reference< script::XInvocation > *)0 ); + TYPELIB_DANGER_GET( &pTD, rInvType.getTypeLibType() ); + typelib_InterfaceTypeDescription * pITD; + pITD = reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD); + if( ! pITD->aBase.bComplete ) + typelib_typedescription_complete( &pTD ); + ::typelib_typedescriptionreference_getDescription( + &m_pInvokMethodTD, pITD->ppMembers[ 1 ] ); // invoke() + ::typelib_typedescriptionreference_getDescription( + &m_pSetValueTD, pITD->ppMembers[ 2 ] ); // setValue() + ::typelib_typedescriptionreference_getDescription( + &m_pGetValueTD, pITD->ppMembers[ 3 ] ); // getValue() + // script.XTypeConverter + const Type & rTCType = + ::getCppuType( (const Reference< script::XTypeConverter > *)0 ); + TYPELIB_DANGER_GET( &pTD, rTCType.getTypeLibType() ); + pITD = reinterpret_cast<typelib_InterfaceTypeDescription*>(pTD); + ::typelib_typedescriptionreference_getDescription( + &m_pConvertToTD, pITD->ppMembers[ 0 ] ); // convertTo() + TYPELIB_DANGER_RELEASE( pTD ); + + if (!m_pInvokMethodTD || !m_pSetValueTD || !m_pGetValueTD || + !m_pConvertToTD || + !m_pAnySeqTD || !m_pShortSeqTD) + { + throw RuntimeException( + OUSTR("missing type descriptions!"), Reference< XInterface >() ); + } + + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); +} +//______________________________________________________________________________ +FactoryImpl::~FactoryImpl() SAL_THROW( () ) +{ + ::typelib_typedescription_release( m_pInvokMethodTD ); + ::typelib_typedescription_release( m_pSetValueTD ); + ::typelib_typedescription_release( m_pGetValueTD ); + ::typelib_typedescription_release( m_pAnySeqTD ); + ::typelib_typedescription_release( m_pShortSeqTD ); + ::typelib_typedescription_release( m_pConvertToTD ); + + (*m_pConverter->release)( m_pConverter ); + +#if OSL_DEBUG_LEVEL > 1 + OSL_ENSURE( m_receiver2adapters.empty(), "### still adapters out there!?" ); +#endif + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +//------------------------------------------------------------------------------ +static inline AdapterImpl * lookup_adapter( + t_ptr_set ** pp_adapter_set, + t_ptr_map & map, void * key, Sequence< Type > const & rTypes ) + SAL_THROW( () ) +{ + t_ptr_set & adapters_set = map[ key ]; + *pp_adapter_set = &adapters_set; + if (adapters_set.empty()) + return 0; // shortcut + // find matching adapter + Type const * pTypes = rTypes.getConstArray(); + sal_Int32 nTypes = rTypes.getLength(); + t_ptr_set::const_iterator iPos( adapters_set.begin() ); + t_ptr_set::const_iterator const iEnd( adapters_set.end() ); + while (iEnd != iPos) + { + AdapterImpl * that = reinterpret_cast< AdapterImpl * >( *iPos ); + // iterate thru all types if that is a matching adapter + sal_Int32 nPosTypes; + for ( nPosTypes = nTypes; nPosTypes--; ) + { + Type const & rType = pTypes[ nPosTypes ]; + // find in adapter's type list + sal_Int32 nPos; + for ( nPos = that->m_nInterfaces; nPos--; ) + { + if (::typelib_typedescriptionreference_isAssignableFrom( + rType.getTypeLibType(), + ((typelib_TypeDescription *)that-> + m_pInterfaces[ nPos ].m_pTypeDescr)->pWeakRef )) + { + // found + break; + } + } + if (nPos < 0) // type not found => next adapter + break; + } + if (nPosTypes < 0) // all types found + return that; + ++iPos; + } + return 0; +} + +// XInvocationAdapterFactory2 impl +//______________________________________________________________________________ +Reference< XInterface > FactoryImpl::createAdapter( + const Reference< script::XInvocation > & xReceiver, + const Sequence< Type > & rTypes ) + throw (RuntimeException) +{ + Reference< XInterface > xRet; + if (xReceiver.is() && rTypes.getLength()) + { + t_ptr_set * adapter_set; + AdapterImpl * that; + Reference< XInterface > xKey( xReceiver, UNO_QUERY ); + { + ClearableMutexGuard guard( m_mutex ); + that = lookup_adapter( + &adapter_set, m_receiver2adapters, xKey.get(), rTypes ); + if (0 == that) // no entry + { + guard.clear(); + // create adapter; already acquired: m_nRef == 1 + AdapterImpl * pNew = + new AdapterImpl( xKey.get(), xReceiver, rTypes, this ); + // lookup again + ClearableMutexGuard guard2( m_mutex ); + that = lookup_adapter( + &adapter_set, m_receiver2adapters, xKey.get(), rTypes ); + if (0 == that) // again no entry + { + pair< t_ptr_set::iterator, bool > insertion( + adapter_set->insert( pNew ) ); + OSL_ASSERT( insertion.second ); + that = pNew; + } + else + { + that->acquire(); + guard2.clear(); + delete pNew; // has never been inserted + } + } + else // found adapter + { + that->acquire(); + } + } + // map one interface to C++ + uno_Interface * pUnoI = &that->m_pInterfaces[ 0 ]; + m_aUno2Cpp.mapInterface( + (void **)&xRet, pUnoI, ::getCppuType( &xRet ) ); + that->release(); + OSL_ASSERT( xRet.is() ); + if (! xRet.is()) + { + throw RuntimeException( + OUSTR("mapping UNO to C++ failed!"), + Reference< XInterface >() ); + } + } + return xRet; +} +// XInvocationAdapterFactory impl +//______________________________________________________________________________ +Reference< XInterface > FactoryImpl::createAdapter( + const Reference< script::XInvocation > & xReceiver, const Type & rType ) + throw (RuntimeException) +{ + return createAdapter( xReceiver, Sequence< Type >( &rType, 1 ) ); +} + +// XServiceInfo +//______________________________________________________________________________ +OUString FactoryImpl::getImplementationName() + throw (RuntimeException) +{ + return invadp_getImplementationName(); +} +//______________________________________________________________________________ +sal_Bool FactoryImpl::supportsService( const OUString & rServiceName ) + throw (RuntimeException) +{ + const Sequence< OUString > & rSNL = getSupportedServiceNames(); + const OUString * pArray = rSNL.getConstArray(); + for ( sal_Int32 nPos = rSNL.getLength(); nPos--; ) + { + if (pArray[nPos].equals( rServiceName )) + return sal_True; + } + return sal_False; +} +//______________________________________________________________________________ +Sequence< OUString > FactoryImpl::getSupportedServiceNames() + throw (RuntimeException) +{ + return invadp_getSupportedServiceNames(); +} + +//============================================================================== +static Reference< XInterface > SAL_CALL FactoryImpl_create( + const Reference< XComponentContext > & xContext ) + throw (Exception) +{ + Reference< XInterface > rRet; + { + MutexGuard guard( Mutex::getGlobalMutex() ); + static WeakReference < XInterface > rwInstance; + rRet = rwInstance; + + if( ! rRet.is() ) + { + rRet = (::cppu::OWeakObject *)new FactoryImpl( xContext ); + rwInstance = rRet; + } + } + return rRet; +} + +} + + +//############################################################################## +//############################################################################## +//############################################################################## + +static struct ::cppu::ImplementationEntry g_entries[] = +{ + { + ::stoc_invadp::FactoryImpl_create, + ::stoc_invadp::invadp_getImplementationName, + ::stoc_invadp::invadp_getSupportedServiceNames, + ::cppu::createSingleComponentFactory, + &::stoc_invadp::g_moduleCount.modCnt , 0 + }, + { 0, 0, 0, 0, 0, 0 } +}; + +extern "C" +{ +sal_Bool SAL_CALL component_canUnload( + TimeValue *pTime ) +{ + return ::stoc_invadp::g_moduleCount.canUnload( + &::stoc_invadp::g_moduleCount, pTime ); +} + +//============================================================================== +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +//============================================================================== +void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) +{ + return ::cppu::component_getFactoryHelper( + pImplName, pServiceManager, pRegistryKey , g_entries ); +} +} diff --git a/stoc/source/invocation_adapterfactory/invadp.xml b/stoc/source/invocation_adapterfactory/invadp.xml new file mode 100644 index 000000000000..e0585b88efe4 --- /dev/null +++ b/stoc/source/invocation_adapterfactory/invadp.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + <module-name> invocadapt.uno </module-name> + <component-description> + <author> Daniel Boelzle </author> + <name> com.sun.star.comp.stoc.InvocationAdapterFactory </name> + <description> +You can create adapter interfaces of any given type for an invocation +interface by using an adapter factory instance. +</description> + <loader-name> com.sun.star.loader.SharedLibrary </loader-name> + <language> C++ </language> + <status value="final"/> + <supported-service> com.sun.star.script.InvocationAdapterFactory </supported-service> + <type> com.sun.star.script.XTypeConverter </type> + <type> com.sun.star.script.XInvocationAdapterFactory </type> + <type> com.sun.star.script.XInvocationAdapterFactory2 </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.registry.XSimpleRegistry </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.uno.XComponentContext </type> + <type> com.sun.star.lang.XSingleComponentFactory </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.uno.TypeClass </type> + <type> com.sun.star.container.XEnumerationAccess </type> + <type> com.sun.star.container.XNameContainer </type> + <type> com.sun.star.container.XIndexContainer </type> + <type> com.sun.star.reflection.InvocationTargetException </type> + </component-description> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> sal </project-build-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> sal3 </runtime-module-dependency> +</module-description> diff --git a/stoc/source/invocation_adapterfactory/invocadapt.component b/stoc/source/invocation_adapterfactory/invocadapt.component new file mode 100644 index 000000000000..64f7b2b3691a --- /dev/null +++ b/stoc/source/invocation_adapterfactory/invocadapt.component @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.stoc.InvocationAdapterFactory"> + <service name="com.sun.star.script.InvocationAdapterFactory"/> + </implementation> +</component> diff --git a/stoc/source/invocation_adapterfactory/makefile.mk b/stoc/source/invocation_adapterfactory/makefile.mk new file mode 100644 index 000000000000..4c3450ac8c8d --- /dev/null +++ b/stoc/source/invocation_adapterfactory/makefile.mk @@ -0,0 +1,73 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME=stoc +TARGET = invocadapt.uno +ENABLE_EXCEPTIONS=TRUE +COMP1TYPELIST = invadp + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +DLLPRE = + +# ------------------------------------------------------------------ + +.INCLUDE : ..$/cppumaker.mk + +SLOFILES= \ + $(SLO)$/iafactory.obj + +SHL1TARGET= $(TARGET) + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) + +SHL1VERSIONMAP = $(SOLARENV)/src/unloadablecomponent.map +SHL1RPATH=URELIB + +SHL1DEPN= +SHL1IMPLIB= i$(TARGET) +SHL1LIBS= $(SLB)$/$(TARGET).lib +SHL1DEF= $(MISC)$/$(SHL1TARGET).def + +DEF1NAME= $(SHL1TARGET) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +ALLTAR : $(MISC)/invocadapt.component + +$(MISC)/invocadapt.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + invocadapt.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_URE_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt invocadapt.component diff --git a/stoc/source/javaloader/javaloader.component b/stoc/source/javaloader/javaloader.component new file mode 100644 index 000000000000..bdd3b82d5125 --- /dev/null +++ b/stoc/source/javaloader/javaloader.component @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.stoc.JavaComponentLoader"> + <service name="com.sun.star.loader.Java"/> + <service name="com.sun.star.loader.Java2"/> + </implementation> +</component> diff --git a/stoc/source/javaloader/javaloader.cxx b/stoc/source/javaloader/javaloader.cxx new file mode 100644 index 000000000000..396ff48ec310 --- /dev/null +++ b/stoc/source/javaloader/javaloader.cxx @@ -0,0 +1,480 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + + +#include <cstdarg> +#include <osl/diagnose.h> +#include <osl/process.h> + +#include <rtl/process.h> +#include <rtl/ustrbuf.hxx> + +#include <uno/environment.h> +#include <uno/mapping.hxx> +#include "com/sun/star/uno/RuntimeException.hpp" + +#include <cppuhelper/servicefactory.hxx> + +#ifdef LINUX +#undef minor +#undef major +#endif + +#include <com/sun/star/java/XJavaVM.hpp> + +#include <com/sun/star/lang/XMultiComponentFactory.hpp> + +#include "jni.h" + +#include <cppuhelper/factory.hxx> +#include <cppuhelper/implementationentry.hxx> + +#include <cppuhelper/implbase2.hxx> + +#include <com/sun/star/loader/XImplementationLoader.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> + +#include "jvmaccess/unovirtualmachine.hxx" +#include "jvmaccess/virtualmachine.hxx" + +namespace css = com::sun::star; + +using namespace ::com::sun::star::java; +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; +using namespace ::osl; + +namespace stoc_javaloader { + +static Mutex & getInitMutex(); + +static Sequence< OUString > loader_getSupportedServiceNames() +{ + static Sequence < OUString > *pNames = 0; + if( ! pNames ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( !pNames ) + { + static Sequence< OUString > seqNames(2); + seqNames.getArray()[0] = OUString( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.loader.Java") ); + seqNames.getArray()[1] = OUString( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.loader.Java2") ); + pNames = &seqNames; + } + } + return *pNames; +} + +static OUString loader_getImplementationName() +{ + static OUString *pImplName = 0; + if( ! pImplName ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( ! pImplName ) + { + static OUString implName( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.stoc.JavaComponentLoader" ) ); + pImplName = &implName; + } + } + return *pImplName; +} + +class JavaComponentLoader : public WeakImplHelper2<XImplementationLoader, XServiceInfo> +{ + css::uno::Reference<XComponentContext> m_xComponentContext; + /** Do not use m_javaLoader directly. Instead use getJavaLoader. + */ + css::uno::Reference<XImplementationLoader> m_javaLoader; + /** The retured Reference contains a null pointer if the office is not configured + to run java. + + @exception com::sun::star::uno::RuntimeException + If the Java implementation of the loader could not be obtained, for reasons other + then that java was not configured the RuntimeException is thrown. + */ + const css::uno::Reference<XImplementationLoader> & getJavaLoader(); + + +public: + JavaComponentLoader(const css::uno::Reference<XComponentContext> & xCtx) + throw(RuntimeException); + virtual ~JavaComponentLoader() throw(); + +public: + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() throw(RuntimeException); + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) + throw(RuntimeException); + virtual Sequence<OUString> SAL_CALL getSupportedServiceNames() + throw(RuntimeException); + + // XImplementationLoader + virtual css::uno::Reference<XInterface> SAL_CALL activate( + const OUString& implementationName, const OUString& implementationLoaderUrl, + const OUString& locationUrl, const css::uno::Reference<XRegistryKey>& xKey) + throw(CannotActivateFactoryException, RuntimeException); + virtual sal_Bool SAL_CALL writeRegistryInfo( + const css::uno::Reference<XRegistryKey>& xKey, + const OUString& implementationLoaderUrl, const OUString& locationUrl) + throw(CannotRegisterImplementationException, RuntimeException); +}; + +const css::uno::Reference<XImplementationLoader> & JavaComponentLoader::getJavaLoader() +{ + MutexGuard aGuard(getInitMutex()); + + if (m_javaLoader.is()) + return m_javaLoader; + + uno_Environment * pJava_environment = NULL; + uno_Environment * pUno_environment = NULL; + typelib_InterfaceTypeDescription * pType_XImplementationLoader = 0; + + try { + // get a java vm, where we can create a loader + css::uno::Reference<XJavaVM> javaVM_xJavaVM( + m_xComponentContext->getValueByName( + OUString(RTL_CONSTASCII_USTRINGPARAM( + "/singletons/" + "com.sun.star.java.theJavaVirtualMachine"))), + UNO_QUERY_THROW); + + // Use the special protocol of XJavaVM.getJavaVM: If the passed in + // process ID has an extra 17th byte of value one, the returned any + // contains a pointer to a jvmaccess::UnoVirtualMachine, instead of the + // underlying JavaVM pointer: + Sequence<sal_Int8> processID(17); + rtl_getGlobalProcessId(reinterpret_cast<sal_uInt8 *>(processID.getArray())); + processID[16] = 1; + + // We get a non-refcounted pointer to a jvmaccess::UnoVirtualMachine + // from the XJavaVM service (the pointer is guaranteed to be valid + // as long as our reference to the XJavaVM service lasts), and + // convert the non-refcounted pointer into a refcounted one + // immediately: + OSL_ENSURE(sizeof (sal_Int64) + >= sizeof (jvmaccess::UnoVirtualMachine *), + "Pointer cannot be represented as sal_Int64"); + sal_Int64 nPointer = reinterpret_cast< sal_Int64 >( + static_cast< jvmaccess::UnoVirtualMachine * >(0)); + javaVM_xJavaVM->getJavaVM(processID) >>= nPointer; + rtl::Reference< jvmaccess::UnoVirtualMachine > xVirtualMachine( + reinterpret_cast< jvmaccess::UnoVirtualMachine * >(nPointer)); + if (!xVirtualMachine.is()) + //throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( + // "javaloader error - JavaVirtualMachine service could not provide a VM")), + // css::uno::Reference<XInterface>()); + // We must not throw a RuntimeException, because this might end the applications. + // It is ok if java components + // are not working because the office can be installed without Java support. + return m_javaLoader; // null-ref + + try + { + jvmaccess::VirtualMachine::AttachGuard aGuard2( + xVirtualMachine->getVirtualMachine()); + JNIEnv * pJNIEnv = aGuard2.getEnvironment(); + + // instantiate the java JavaLoader + jclass jcClassLoader = pJNIEnv->FindClass("java/lang/ClassLoader"); + if(pJNIEnv->ExceptionOccurred()) + throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "javaloader error - could not find class java/lang/ClassLoader")), + css::uno::Reference<XInterface>()); + jmethodID jmLoadClass = pJNIEnv->GetMethodID( + jcClassLoader, "loadClass", + "(Ljava/lang/String;)Ljava/lang/Class;"); + if(pJNIEnv->ExceptionOccurred()) + throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "javaloader error - could not find method java/lang/ClassLoader.loadClass")), + css::uno::Reference<XInterface>()); + jvalue arg; + arg.l = pJNIEnv->NewStringUTF( + "com.sun.star.comp.loader.JavaLoader"); + if(pJNIEnv->ExceptionOccurred()) + throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "javaloader error - could not create string")), + css::uno::Reference<XInterface>()); + jclass jcJavaLoader = static_cast< jclass >( + pJNIEnv->CallObjectMethodA( + static_cast< jobject >(xVirtualMachine->getClassLoader()), + jmLoadClass, &arg)); + if(pJNIEnv->ExceptionOccurred()) + throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "javaloader error - could not find class com/sun/star/comp/loader/JavaLoader")), + css::uno::Reference<XInterface>()); + jmethodID jmJavaLoader_init = pJNIEnv->GetMethodID(jcJavaLoader, "<init>", "()V"); + if(pJNIEnv->ExceptionOccurred()) + throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "javaloader error - instantiation of com.sun.star.comp.loader.JavaLoader failed")), + css::uno::Reference<XInterface>()); + jobject joJavaLoader = pJNIEnv->NewObject(jcJavaLoader, jmJavaLoader_init); + if(pJNIEnv->ExceptionOccurred()) + throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "javaloader error - instantiation of com.sun.star.comp.loader.JavaLoader failed")), + css::uno::Reference<XInterface>()); + + // map the java JavaLoader to this environment + OUString sJava(RTL_CONSTASCII_USTRINGPARAM("java")); + uno_getEnvironment(&pJava_environment, sJava.pData, + xVirtualMachine.get()); + if(!pJava_environment) + throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "javaloader error - no Java environment available")), css::uno::Reference<XInterface>()); + + // why is there no convinient contructor? + OUString sCppu_current_lb_name(RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME)); + uno_getEnvironment(&pUno_environment, sCppu_current_lb_name.pData, NULL); + if(!pUno_environment) + throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "javaloader error - no C++ environment available")), css::uno::Reference<XInterface>()); + + Mapping java_curr(pJava_environment, pUno_environment); + if(!java_curr.is()) + throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "javaloader error - no mapping from java to C++ ")), css::uno::Reference<XInterface>()); + + // release java environment + pJava_environment->release(pJava_environment); + pJava_environment = NULL; + + // release uno environment + pUno_environment->release(pUno_environment); + pUno_environment = NULL; + + getCppuType((css::uno::Reference<XImplementationLoader> *) 0). + getDescription((typelib_TypeDescription **) & pType_XImplementationLoader); + if(!pType_XImplementationLoader) + throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "javaloader error - no type information for XImplementationLoader")), + css::uno::Reference<XInterface>()); + + m_javaLoader = css::uno::Reference<XImplementationLoader>(reinterpret_cast<XImplementationLoader *>( + java_curr.mapInterface(joJavaLoader, pType_XImplementationLoader))); + pJNIEnv->DeleteLocalRef( joJavaLoader ); + if(!m_javaLoader.is()) + throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "javaloader error - mapping of java XImplementationLoader to c++ failed")), + css::uno::Reference<XInterface>()); + + typelib_typedescription_release(reinterpret_cast<typelib_TypeDescription *>(pType_XImplementationLoader)); + pType_XImplementationLoader = NULL; + } + catch (jvmaccess::VirtualMachine::AttachGuard::CreationException &) + { + throw RuntimeException( + OUString(RTL_CONSTASCII_USTRINGPARAM( + "jvmaccess::VirtualMachine::AttachGuard" + "::CreationException")),0); + } + + // set the service manager at the javaloader + css::uno::Reference<XInitialization> javaLoader_XInitialization(m_javaLoader, UNO_QUERY); + if(!javaLoader_XInitialization.is()) + throw RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM( + "javaloader error - initialization of java javaloader failed, no XInitialization")), + css::uno::Reference<XInterface>()); + + Any any; + any <<= css::uno::Reference<XMultiComponentFactory>( + m_xComponentContext->getServiceManager()); + + javaLoader_XInitialization->initialize(Sequence<Any>(&any, 1)); + } + catch(RuntimeException &) { + if(pJava_environment) + pJava_environment->release(pJava_environment); + + if(pUno_environment) + pUno_environment->release(pUno_environment); + + if(pType_XImplementationLoader) + typelib_typedescription_release( + reinterpret_cast<typelib_TypeDescription *>(pType_XImplementationLoader)); + throw; + } + OSL_TRACE("javaloader.cxx: mapped javaloader - 0x%x", m_javaLoader.get()); + return m_javaLoader; +} + +JavaComponentLoader::JavaComponentLoader(const css::uno::Reference<XComponentContext> & xCtx) throw(RuntimeException) : + m_xComponentContext(xCtx) + +{ + +} + +JavaComponentLoader::~JavaComponentLoader() throw() +{ +} + +// XServiceInfo +OUString SAL_CALL JavaComponentLoader::getImplementationName() + throw(::com::sun::star::uno::RuntimeException) +{ + return loader_getImplementationName(); +} + +sal_Bool SAL_CALL JavaComponentLoader::supportsService(const OUString & ServiceName) + throw(::com::sun::star::uno::RuntimeException) +{ + sal_Bool bSupport = sal_False; + + Sequence<OUString> aSNL = getSupportedServiceNames(); + const OUString * pArray = aSNL.getArray(); + for(sal_Int32 i = 0; i < aSNL.getLength() && !bSupport; ++ i) + bSupport = pArray[i] == ServiceName; + + return bSupport; +} + +Sequence<OUString> SAL_CALL JavaComponentLoader::getSupportedServiceNames() + throw(::com::sun::star::uno::RuntimeException) +{ + return loader_getSupportedServiceNames(); +} + + + +// XImplementationLoader +sal_Bool SAL_CALL JavaComponentLoader::writeRegistryInfo( + const css::uno::Reference<XRegistryKey> & xKey, const OUString & blabla, + const OUString & rLibName) + throw(CannotRegisterImplementationException, RuntimeException) +{ + const css::uno::Reference<XImplementationLoader> & loader = getJavaLoader(); + if (loader.is()) + return loader->writeRegistryInfo(xKey, blabla, rLibName); + else + throw CannotRegisterImplementationException( + OUString(RTL_CONSTASCII_USTRINGPARAM("Could not create Java implementation loader")), NULL); +} + + +css::uno::Reference<XInterface> SAL_CALL JavaComponentLoader::activate( + const OUString & rImplName, const OUString & blabla, const OUString & rLibName, + const css::uno::Reference<XRegistryKey> & xKey) + throw(CannotActivateFactoryException, RuntimeException) +{ + const css::uno::Reference<XImplementationLoader> & loader = getJavaLoader(); + if (loader.is()) + return loader->activate(rImplName, blabla, rLibName, xKey); + else + throw CannotActivateFactoryException( + OUString(RTL_CONSTASCII_USTRINGPARAM("Could not create Java implementation loader")), NULL); +} + +static Mutex & getInitMutex() +{ + static Mutex * pMutex = 0; + if( ! pMutex ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( ! pMutex ) + { + static Mutex mutex; + pMutex = &mutex; + } + } + return *pMutex; +} + +css::uno::Reference<XInterface> SAL_CALL JavaComponentLoader_CreateInstance(const css::uno::Reference<XComponentContext> & xCtx) throw(Exception) +{ + css::uno::Reference<XInterface> xRet; + + try { + MutexGuard guard( getInitMutex() ); + // The javaloader is never destroyed and there can be only one! + // Note that the first context wins .... + static css::uno::Reference< XInterface > *pStaticRef = 0; + if( pStaticRef ) + { + xRet = *pStaticRef; + } + else + { + xRet = *new JavaComponentLoader(xCtx); + pStaticRef = new css::uno::Reference< XInterface > ( xRet ); + } + } + catch(RuntimeException & runtimeException) { + OString message = OUStringToOString(runtimeException.Message, RTL_TEXTENCODING_ASCII_US); + osl_trace("javaloader - could not init javaloader cause of %s", message.getStr()); + throw; + } + + return xRet; +} + +} //end namespace + + +using namespace stoc_javaloader; + +static struct ImplementationEntry g_entries[] = +{ + { + JavaComponentLoader_CreateInstance, loader_getImplementationName, + loader_getSupportedServiceNames, createSingleComponentFactory, + 0 , 0 + }, + { 0, 0, 0, 0, 0, 0 } +}; + +extern "C" +{ +// NOTE: component_canUnload is not exported, as the library cannot be unloaded. + +//================================================================================================== +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} +//================================================================================================== +void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) +{ + return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries ); +} +} diff --git a/stoc/source/javaloader/javaloader.xml b/stoc/source/javaloader/javaloader.xml new file mode 100644 index 000000000000..fffddb4459c4 --- /dev/null +++ b/stoc/source/javaloader/javaloader.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + <module-name> javaloader.uno </module-name> + <component-description> + <author> Kay Ramme </author> + <name> com.sun.star.comp.stoc.JavaComponentLoader </name> + <description> ... </description> + <loader-name> com.sun.star.loader.SharedLibrary </loader-name> + <language> c++ </language> + <status value="final"/> + <supported-service> com.sun.star.loader.Java </supported-service> + <supported-service> com.sun.star.loader.Java2 </supported-service> + <service-dependency> ... </service-dependency> + + <type> com.sun.star.java.XJavaVM </type> + <type> com.sun.star.lang.IllegalArgumentException </type> + <type> com.sun.star.lang.XInitialization </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.XMultiComponentFactory </type> + <type> com.sun.star.lang.XSingleComponentFactory </type> + <type> com.sun.star.loader.XImplementationLoader </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.uno.TypeClass </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.uno.XWeak </type> + </component-description> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> sal </project-build-dependency> + <project-build-dependency> jvmaccess </project-build-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> sal3 </runtime-module-dependency> + <runtime-module-dependency> jvmaccess3$(COM) </runtime-module-dependency> +</module-description> diff --git a/stoc/source/javaloader/makefile.mk b/stoc/source/javaloader/makefile.mk new file mode 100644 index 000000000000..e53b90d5e6e7 --- /dev/null +++ b/stoc/source/javaloader/makefile.mk @@ -0,0 +1,79 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=stoc +TARGET = javaloader.uno +ENABLE_EXCEPTIONS=TRUE +COMP1TYPELIST = javaloader + +.IF "$(SOLAR_JAVA)" == "TRUE" +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +DLLPRE = + +# ------------------------------------------------------------------ + +.INCLUDE : ..$/cppumaker.mk + +SLOFILES= $(SLO)$/javaloader.obj + +SHL1TARGET= $(TARGET) + +SHL1STDLIBS=\ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(JVMACCESSLIB) + +SHL1VERSIONMAP = $(SOLARENV)/src/component.map +SHL1DEPN= +SHL1IMPLIB= i$(TARGET) +SHL1LIBS= $(SLB)$/$(TARGET).lib +SHL1DEF= $(MISC)$/$(SHL1TARGET).def +SHL1RPATH= URELIB + +DEF1NAME= $(SHL1TARGET) + +.ELSE # SOLAR_JAVA +all: + @echo Nothing to do: SOLAR_JAVA not set +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +ALLTAR : $(MISC)/javaloader.component + +$(MISC)/javaloader.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + javaloader.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_URE_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt javaloader.component diff --git a/stoc/source/javavm/interact.cxx b/stoc/source/javavm/interact.cxx new file mode 100644 index 000000000000..024d34acf12e --- /dev/null +++ b/stoc/source/javavm/interact.cxx @@ -0,0 +1,125 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include "interact.hxx" + +#include "com/sun/star/java/JavaDisabledException.hpp" +#include "com/sun/star/java/JavaVMCreationFailureException.hpp" +#include "com/sun/star/task/XInteractionAbort.hpp" +#include "com/sun/star/task/XInteractionRetry.hpp" +#include "com/sun/star/task/XInteractionContinuation.hpp" +#include "cppuhelper/implbase1.hxx" +#include "osl/mutex.hxx" + +namespace css = com::sun::star; + +using stoc_javavm::InteractionRequest; + +namespace { + +class AbortContinuation: + public cppu::WeakImplHelper1< css::task::XInteractionAbort > +{ +public: + inline AbortContinuation() {} + + virtual inline void SAL_CALL select() throw (css::uno::RuntimeException) {} + +private: + AbortContinuation(AbortContinuation &); // not implemented + void operator =(AbortContinuation); // not implemented + + virtual inline ~AbortContinuation() {} +}; + +} + +class InteractionRequest::RetryContinuation: + public cppu::WeakImplHelper1< css::task::XInteractionRetry > +{ +public: + inline RetryContinuation(): m_bSelected(false) {} + + virtual void SAL_CALL select() throw (css::uno::RuntimeException); + + bool isSelected() const; + +private: + RetryContinuation(RetryContinuation &); // not implemented + void operator =(RetryContinuation); // not implemented + + virtual inline ~RetryContinuation() {} + + mutable osl::Mutex m_aMutex; + bool m_bSelected; +}; + +void SAL_CALL InteractionRequest::RetryContinuation::select() + throw (css::uno::RuntimeException) +{ + osl::MutexGuard aGuard(m_aMutex); + m_bSelected = true; +} + +bool InteractionRequest::RetryContinuation::isSelected() const +{ + osl::MutexGuard aGuard(m_aMutex); + return m_bSelected; +} + +InteractionRequest::InteractionRequest(css::uno::Any const & rRequest): + m_aRequest(rRequest) +{ + m_aContinuations.realloc(2); + m_xRetryContinuation = new RetryContinuation; + m_aContinuations[0] = new AbortContinuation; + m_aContinuations[1] = m_xRetryContinuation.get(); +} + +css::uno::Any SAL_CALL InteractionRequest::getRequest() + throw (css::uno::RuntimeException) +{ + return m_aRequest; +} + +css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > +SAL_CALL InteractionRequest::getContinuations() + throw (css::uno::RuntimeException) +{ + return m_aContinuations; +} + +bool InteractionRequest::retry() const +{ + return m_xRetryContinuation.is() && m_xRetryContinuation->isSelected(); +} + +InteractionRequest::~InteractionRequest() +{} diff --git a/stoc/source/javavm/interact.hxx b/stoc/source/javavm/interact.hxx new file mode 100644 index 000000000000..7db3fd949b68 --- /dev/null +++ b/stoc/source/javavm/interact.hxx @@ -0,0 +1,75 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#if !defined INCLUDED_STOC_JAVAVM_INTERACT_HXX +#define INCLUDED_STOC_JAVAVM_INTERACT_HXX + +#include "com/sun/star/task/XInteractionRequest.hpp" +#include "com/sun/star/uno/Any.hxx" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "cppuhelper/implbase1.hxx" +#include "rtl/ref.hxx" + +namespace com { namespace sun { namespace star { namespace task { + class XInteractionContinuation; +} } } } + +namespace stoc_javavm { + +class InteractionRequest: + public cppu::WeakImplHelper1< com::sun::star::task::XInteractionRequest > +{ +public: + explicit InteractionRequest(com::sun::star::uno::Any const & rRequest); + + virtual com::sun::star::uno::Any SAL_CALL getRequest() + throw (com::sun::star::uno::RuntimeException); + + virtual com::sun::star::uno::Sequence< com::sun::star::uno::Reference< + com::sun::star::task::XInteractionContinuation > > SAL_CALL + getContinuations() throw (com::sun::star::uno::RuntimeException); + + bool retry() const; + +private: + class RetryContinuation; + + InteractionRequest(InteractionRequest &); // not implemented + void operator =(InteractionRequest); // not implemented + + virtual ~InteractionRequest(); + + com::sun::star::uno::Any m_aRequest; + com::sun::star::uno::Sequence< com::sun::star::uno::Reference< + com::sun::star::task::XInteractionContinuation > > m_aContinuations; + rtl::Reference< RetryContinuation > m_xRetryContinuation; +}; + +} + +#endif // INCLUDED_STOC_JAVAVM_INTERACT_HXX diff --git a/stoc/source/javavm/javavm.component b/stoc/source/javavm/javavm.component new file mode 100644 index 000000000000..f78d8af3ac29 --- /dev/null +++ b/stoc/source/javavm/javavm.component @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.stoc.JavaVirtualMachine"> + <service name="com.sun.star.java.JavaVirtualMachine"/> + <singleton name="com.sun.star.java.theJavaVirtualMachine"/> + </implementation> +</component> diff --git a/stoc/source/javavm/javavm.cxx b/stoc/source/javavm/javavm.cxx new file mode 100644 index 000000000000..1ea792270861 --- /dev/null +++ b/stoc/source/javavm/javavm.cxx @@ -0,0 +1,1776 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include "javavm.hxx" + +#include "interact.hxx" +#include "jvmargs.hxx" + +#include "com/sun/star/beans/NamedValue.hpp" +#include "com/sun/star/beans/PropertyState.hpp" +#include "com/sun/star/beans/PropertyValue.hpp" +#include "com/sun/star/container/XContainer.hpp" +#include "com/sun/star/java/JavaNotFoundException.hpp" +#include "com/sun/star/java/InvalidJavaSettingsException.hpp" +#include "com/sun/star/java/RestartRequiredException.hpp" +#include "com/sun/star/java/JavaDisabledException.hpp" +#include "com/sun/star/java/JavaVMCreationFailureException.hpp" +#include "com/sun/star/lang/DisposedException.hpp" +#include "com/sun/star/lang/IllegalArgumentException.hpp" +#include "com/sun/star/lang/XEventListener.hpp" +#include "com/sun/star/lang/XMultiComponentFactory.hpp" +#include "com/sun/star/lang/XSingleComponentFactory.hpp" +#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp" +#include "com/sun/star/registry/XRegistryKey.hpp" +#include "com/sun/star/registry/XSimpleRegistry.hpp" +#include "com/sun/star/task/XInteractionHandler.hpp" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uno/XCurrentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/util/XMacroExpander.hpp" +#include "com/sun/star/container/XNameAccess.hpp" +#include "cppuhelper/exc_hlp.hxx" +#include "cppuhelper/factory.hxx" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "jvmaccess/classpath.hxx" +#include "jvmaccess/unovirtualmachine.hxx" +#include "jvmaccess/virtualmachine.hxx" +#include "osl/file.hxx" +#include "osl/thread.h" +#include "rtl/bootstrap.hxx" +#include "rtl/process.h" +#include "rtl/string.h" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "rtl/uri.hxx" +#include "sal/types.h" +#include "uno/current_context.hxx" +#include "uno/environment.h" +#include "uno/lbnames.h" +#include "jvmfwk/framework.h" +#include "jni.h" + +#include <stack> +#include <string.h> +#include <time.h> +#include <memory> +#include <vector> +#include "boost/scoped_array.hpp" +#define OUSTR(x) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( x )) + +// Properties of the javavm can be put +// as a komma separated list in this +// environment variable +#define PROPERTIES_ENV "OO_JAVA_PROPERTIES" +#ifdef UNIX +#define INI_FILE "javarc" +#ifdef MACOSX +#define DEF_JAVALIB "JavaVM.framework" +#else +#define DEF_JAVALIB "libjvm.so" +#endif +#define TIMEZONE "MEZ" +#else +#define INI_FILE "java.ini" +#define DEF_JAVALIB "jvm.dll" +#define TIMEZONE "MET" +#endif + +/* Within this implementation of the com.sun.star.java.JavaVirtualMachine + * service and com.sun.star.java.theJavaVirtualMachine singleton, the method + * com.sun.star.java.XJavaVM.getJavaVM relies on the following: + * 1 The string "$URE_INTERNAL_JAVA_DIR/" is expanded via the + * com.sun.star.util.theMacroExpander singleton into an internal (see the + * com.sun.star.uri.ExternalUriReferenceTranslator service), hierarchical URI + * reference relative to which the URE JAR files can be addressed. + * 2 The string "$URE_INTERNAL_JAVA_CLASSPATH" is either not expandable via the + * com.sun.star.util.theMacroExpander singleton + * (com.sun.star.lang.IllegalArgumentException), or is expanded via the + * com.sun.star.util.theMacroExpander singleton into a list of zero or more + * internal (see the com.sun.star.uri.ExternalUriReferenceTranslator service) + * URIs, where any space characters (U+0020) are ignored (and, in particular, + * separate adjacent URIs). + * If either of these requirements is not met, getJavaVM raises a + * com.sun.star.uno.RuntimeException. + */ + +namespace css = com::sun::star; + +using stoc_javavm::JavaVirtualMachine; + +namespace { + + + +class NoJavaIniException: public css::uno::Exception +{ +}; + +class SingletonFactory: + private cppu::WeakImplHelper1< css::lang::XEventListener > +{ +public: + static css::uno::Reference< css::uno::XInterface > getSingleton( + css::uno::Reference< css::uno::XComponentContext > const & rContext); + +private: + SingletonFactory(SingletonFactory &); // not implemented + void operator =(SingletonFactory); // not implemented + + inline SingletonFactory() {} + + virtual inline ~SingletonFactory() {} + + virtual void SAL_CALL disposing(css::lang::EventObject const &) + throw (css::uno::RuntimeException); + + static void dispose(); + + // TODO ok to keep these static? + static osl::Mutex m_aMutex; + static css::uno::Reference< css::uno::XInterface > m_xSingleton; + static bool m_bDisposed; +}; + +css::uno::Reference< css::uno::XInterface > SingletonFactory::getSingleton( + css::uno::Reference< css::uno::XComponentContext > const & rContext) +{ + css::uno::Reference< css::uno::XInterface > xSingleton; + css::uno::Reference< css::lang::XComponent > xComponent; + { + osl::MutexGuard aGuard(m_aMutex); + if (!m_xSingleton.is()) + { + if (m_bDisposed) + throw css::lang::DisposedException(); + xComponent = css::uno::Reference< css::lang::XComponent >( + rContext, css::uno::UNO_QUERY_THROW); + m_xSingleton = static_cast< cppu::OWeakObject * >( + new JavaVirtualMachine(rContext)); + } + xSingleton = m_xSingleton; + } + if (xComponent.is()) + try + { + xComponent->addEventListener(new SingletonFactory); + } + catch (...) + { + dispose(); + throw; + } + return xSingleton; +} + +void SAL_CALL SingletonFactory::disposing(css::lang::EventObject const &) + throw (css::uno::RuntimeException) +{ + dispose(); +} + +void SingletonFactory::dispose() +{ + css::uno::Reference< css::lang::XComponent > xComponent; + { + osl::MutexGuard aGuard(m_aMutex); + xComponent = css::uno::Reference< css::lang::XComponent >( + m_xSingleton, css::uno::UNO_QUERY); + m_xSingleton.clear(); + m_bDisposed = true; + } + if (xComponent.is()) + xComponent->dispose(); +} + +osl::Mutex SingletonFactory::m_aMutex; +css::uno::Reference< css::uno::XInterface > SingletonFactory::m_xSingleton; +bool SingletonFactory::m_bDisposed = false; + +rtl::OUString serviceGetImplementationName() +{ + return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.stoc.JavaVirtualMachine")); +} + +css::uno::Sequence< rtl::OUString > serviceGetSupportedServiceNames() +{ + rtl::OUString aServiceName( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.java.JavaVirtualMachine")); + return css::uno::Sequence< rtl::OUString >(&aServiceName, 1); +} + +css::uno::Reference< css::uno::XInterface > SAL_CALL serviceCreateInstance( + css::uno::Reference< css::uno::XComponentContext > const & rContext) + SAL_THROW((css::uno::Exception)) +{ + // Only one single instance of this service is ever constructed, and is + // available until the component context used to create this instance is + // disposed. Afterwards, this function throws a DisposedException (as do + // all relevant methods on the single service instance). + return SingletonFactory::getSingleton(rContext); +} + +cppu::ImplementationEntry const aServiceImplementation[] + = { { serviceCreateInstance, + serviceGetImplementationName, + serviceGetSupportedServiceNames, + cppu::createSingleComponentFactory, + 0, 0 }, + { 0, 0, 0, 0, 0, 0 } }; + +typedef std::stack< jvmaccess::VirtualMachine::AttachGuard * > GuardStack; + +extern "C" { + +static void destroyAttachGuards(void * pData) +{ + GuardStack * pStack = static_cast< GuardStack * >(pData); + if (pStack != 0) + { + while (!pStack->empty()) + { + delete pStack->top(); + pStack->pop(); + } + delete pStack; + } +} + +} + +bool askForRetry(css::uno::Any const & rException) +{ + css::uno::Reference< css::uno::XCurrentContext > xContext( + css::uno::getCurrentContext()); + if (xContext.is()) + { + css::uno::Reference< css::task::XInteractionHandler > xHandler; + xContext->getValueByName(rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "java-vm.interaction-handler"))) + >>= xHandler; + if (xHandler.is()) + { + rtl::Reference< stoc_javavm::InteractionRequest > xRequest( + new stoc_javavm::InteractionRequest(rException)); + xHandler->handle(xRequest.get()); + return xRequest->retry(); + } + } + return false; +} + +// Only gets the properties if the "Proxy Server" entry in the option dialog is +// set to manual (i.e. not to none) +void getINetPropsFromConfig(stoc_javavm::JVM * pjvm, + const css::uno::Reference<css::lang::XMultiComponentFactory> & xSMgr, + const css::uno::Reference<css::uno::XComponentContext> &xCtx ) throw (css::uno::Exception) +{ + css::uno::Reference<css::uno::XInterface> xConfRegistry = xSMgr->createInstanceWithContext( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.configuration.ConfigurationRegistry")), + xCtx ); + if(!xConfRegistry.is()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("javavm.cxx: couldn't get ConfigurationRegistry")), 0); + + css::uno::Reference<css::registry::XSimpleRegistry> xConfRegistry_simple(xConfRegistry, css::uno::UNO_QUERY); + if(!xConfRegistry_simple.is()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("javavm.cxx: couldn't get ConfigurationRegistry")), 0); + + xConfRegistry_simple->open(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Inet")), sal_True, sal_False); + css::uno::Reference<css::registry::XRegistryKey> xRegistryRootKey = xConfRegistry_simple->getRootKey(); + +// if ooInetProxyType is not 0 then read the settings + css::uno::Reference<css::registry::XRegistryKey> proxyEnable= xRegistryRootKey->openKey(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Settings/ooInetProxyType"))); + if( proxyEnable.is() && 0 != proxyEnable->getLongValue()) + { + // read ftp proxy name + css::uno::Reference<css::registry::XRegistryKey> ftpProxy_name = xRegistryRootKey->openKey(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Settings/ooInetFTPProxyName"))); + if(ftpProxy_name.is() && ftpProxy_name->getStringValue().getLength()) { + rtl::OUString ftpHost = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ftp.proxyHost=")); + ftpHost += ftpProxy_name->getStringValue(); + + // read ftp proxy port + css::uno::Reference<css::registry::XRegistryKey> ftpProxy_port = xRegistryRootKey->openKey(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Settings/ooInetFTPProxyPort"))); + if(ftpProxy_port.is() && ftpProxy_port->getLongValue()) { + rtl::OUString ftpPort = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ftp.proxyPort=")); + ftpPort += rtl::OUString::valueOf(ftpProxy_port->getLongValue()); + + pjvm->pushProp(ftpHost); + pjvm->pushProp(ftpPort); + } + } + + // read http proxy name + css::uno::Reference<css::registry::XRegistryKey> httpProxy_name = xRegistryRootKey->openKey(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Settings/ooInetHTTPProxyName"))); + if(httpProxy_name.is() && httpProxy_name->getStringValue().getLength()) { + rtl::OUString httpHost = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("http.proxyHost=")); + httpHost += httpProxy_name->getStringValue(); + + // read http proxy port + css::uno::Reference<css::registry::XRegistryKey> httpProxy_port = xRegistryRootKey->openKey(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Settings/ooInetHTTPProxyPort"))); + if(httpProxy_port.is() && httpProxy_port->getLongValue()) { + rtl::OUString httpPort = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("http.proxyPort=")); + httpPort += rtl::OUString::valueOf(httpProxy_port->getLongValue()); + + pjvm->pushProp(httpHost); + pjvm->pushProp(httpPort); + } + } + + // read https proxy name + css::uno::Reference<css::registry::XRegistryKey> httpsProxy_name = xRegistryRootKey->openKey(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Settings/ooInetHTTPSProxyName"))); + if(httpsProxy_name.is() && httpsProxy_name->getStringValue().getLength()) { + rtl::OUString httpsHost = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("https.proxyHost=")); + httpsHost += httpsProxy_name->getStringValue(); + + // read https proxy port + css::uno::Reference<css::registry::XRegistryKey> httpsProxy_port = xRegistryRootKey->openKey(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Settings/ooInetHTTPSProxyPort"))); + if(httpsProxy_port.is() && httpsProxy_port->getLongValue()) { + rtl::OUString httpsPort = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("https.proxyPort=")); + httpsPort += rtl::OUString::valueOf(httpsProxy_port->getLongValue()); + + pjvm->pushProp(httpsHost); + pjvm->pushProp(httpsPort); + } + } + + // read nonProxyHosts + css::uno::Reference<css::registry::XRegistryKey> nonProxies_name = xRegistryRootKey->openKey(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Settings/ooInetNoProxy"))); + if(nonProxies_name.is() && nonProxies_name->getStringValue().getLength()) { + rtl::OUString httpNonProxyHosts = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("http.nonProxyHosts=")); + rtl::OUString ftpNonProxyHosts= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ftp.nonProxyHosts=")); + rtl::OUString value= nonProxies_name->getStringValue(); + // replace the separator ";" by "|" + value= value.replace((sal_Unicode)';', (sal_Unicode)'|'); + + httpNonProxyHosts += value; + ftpNonProxyHosts += value; + + pjvm->pushProp(httpNonProxyHosts); + pjvm->pushProp(ftpNonProxyHosts); + } + + // read socks settings +/* Reference<XRegistryKey> socksProxy_name = xRegistryRootKey->openKey(OUSTR("Settings/ooInetSOCKSProxyName")); + if (socksProxy_name.is() && httpProxy_name->getStringValue().getLength()) { + OUString socksHost = OUSTR("socksProxyHost="); + socksHost += socksProxy_name->getStringValue(); + + // read http proxy port + Reference<XRegistryKey> socksProxy_port = xRegistryRootKey->openKey(OUSTR("Settings/ooInetSOCKSProxyPort")); + if (socksProxy_port.is() && socksProxy_port->getLongValue()) { + OUString socksPort = OUSTR("socksProxyPort="); + socksPort += OUString::valueOf(socksProxy_port->getLongValue()); + + pjvm->pushProp(socksHost); + pjvm->pushProp(socksPort); + } + } +*/ } + xConfRegistry_simple->close(); +} + +void getDefaultLocaleFromConfig( + stoc_javavm::JVM * pjvm, + const css::uno::Reference<css::lang::XMultiComponentFactory> & xSMgr, + const css::uno::Reference<css::uno::XComponentContext> &xCtx ) throw(css::uno::Exception) +{ + css::uno::Reference<css::uno::XInterface> xConfRegistry = + xSMgr->createInstanceWithContext( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.ConfigurationRegistry")), xCtx ); + if(!xConfRegistry.is()) + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("javavm.cxx: couldn't get ConfigurationRegistry")), 0); + + css::uno::Reference<css::registry::XSimpleRegistry> xConfRegistry_simple( + xConfRegistry, css::uno::UNO_QUERY); + if(!xConfRegistry_simple.is()) + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("javavm.cxx: couldn't get ConfigurationRegistry")), 0); + + xConfRegistry_simple->open(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Setup")), sal_True, sal_False); + css::uno::Reference<css::registry::XRegistryKey> xRegistryRootKey = xConfRegistry_simple->getRootKey(); + + // read locale + css::uno::Reference<css::registry::XRegistryKey> locale = xRegistryRootKey->openKey(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("L10N/ooLocale"))); + if(locale.is() && locale->getStringValue().getLength()) { + rtl::OUString language; + rtl::OUString country; + + sal_Int32 index = locale->getStringValue().indexOf((sal_Unicode) '-'); + + if(index >= 0) { + language = locale->getStringValue().copy(0, index); + country = locale->getStringValue().copy(index + 1); + + if(language.getLength()) { + rtl::OUString prop(RTL_CONSTASCII_USTRINGPARAM("user.language=")); + prop += language; + + pjvm->pushProp(prop); + } + + if(country.getLength()) { + rtl::OUString prop(RTL_CONSTASCII_USTRINGPARAM("user.country=")); + prop += country; + + pjvm->pushProp(prop); + } + } + } + + xConfRegistry_simple->close(); +} + + + +void getJavaPropsFromSafetySettings( + stoc_javavm::JVM * pjvm, + const css::uno::Reference<css::lang::XMultiComponentFactory> & xSMgr, + const css::uno::Reference<css::uno::XComponentContext> &xCtx) throw(css::uno::Exception) +{ + css::uno::Reference<css::uno::XInterface> xConfRegistry = + xSMgr->createInstanceWithContext( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.ConfigurationRegistry")), + xCtx); + if(!xConfRegistry.is()) + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("javavm.cxx: couldn't get ConfigurationRegistry")), 0); + + css::uno::Reference<css::registry::XSimpleRegistry> xConfRegistry_simple( + xConfRegistry, css::uno::UNO_QUERY); + if(!xConfRegistry_simple.is()) + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("javavm.cxx: couldn't get ConfigurationRegistry")), 0); + + xConfRegistry_simple->open( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Java")), + sal_True, sal_False); + css::uno::Reference<css::registry::XRegistryKey> xRegistryRootKey = + xConfRegistry_simple->getRootKey(); + + if (xRegistryRootKey.is()) + { + css::uno::Reference<css::registry::XRegistryKey> key_NetAccess= xRegistryRootKey->openKey(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("VirtualMachine/NetAccess"))); + if (key_NetAccess.is()) + { + sal_Int32 val= key_NetAccess->getLongValue(); + rtl::OUString sVal; + switch( val) + { + case 0: sVal= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("host")); + break; + case 1: sVal= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("unrestricted")); + break; + case 3: sVal= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("none")); + break; + } + rtl::OUString sProperty( RTL_CONSTASCII_USTRINGPARAM("appletviewer.security.mode=")); + sProperty= sProperty + sVal; + pjvm->pushProp(sProperty); + } + css::uno::Reference<css::registry::XRegistryKey> key_CheckSecurity= xRegistryRootKey->openKey( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("VirtualMachine/Security"))); + if( key_CheckSecurity.is()) + { + sal_Bool val= (sal_Bool) key_CheckSecurity->getLongValue(); + rtl::OUString sProperty(RTL_CONSTASCII_USTRINGPARAM("stardiv.security.disableSecurity=")); + if( val) + sProperty= sProperty + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("false")); + else + sProperty= sProperty + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("true")); + pjvm->pushProp( sProperty); + } + } + xConfRegistry_simple->close(); +} + +static void setTimeZone(stoc_javavm::JVM * pjvm) throw() { + /* A Bug in the Java function + ** struct Hjava_util_Properties * java_lang_System_initProperties( + ** struct Hjava_lang_System *this, + ** struct Hjava_util_Properties *props); + ** This function doesn't detect MEZ, MET or "W. Europe Standard Time" + */ + struct tm *tmData; + time_t clock = time(NULL); + tzset(); + tmData = localtime(&clock); +#ifdef MACOSX + char * p = tmData->tm_zone; +#else + char * p = tzname[0]; +#endif + + if (!strcmp(TIMEZONE, p)) + pjvm->pushProp(rtl::OUString::createFromAscii("user.timezone=ECT")); +} + +void initVMConfiguration( + stoc_javavm::JVM * pjvm, + const css::uno::Reference<css::lang::XMultiComponentFactory> & xSMgr, + const css::uno::Reference<css::uno::XComponentContext > &xCtx) throw(css::uno::Exception) +{ + stoc_javavm::JVM jvm; + try { + getINetPropsFromConfig(&jvm, xSMgr, xCtx); + } + catch(css::uno::Exception & exception) { +#if OSL_DEBUG_LEVEL > 1 + rtl::OString message = rtl::OUStringToOString(exception.Message, RTL_TEXTENCODING_ASCII_US); + OSL_TRACE("javavm.cxx: can not get INetProps cause of >%s<", message.getStr()); +#else + (void) exception; // unused +#endif + } + + try { + getDefaultLocaleFromConfig(&jvm, xSMgr,xCtx); + } + catch(css::uno::Exception & exception) { +#if OSL_DEBUG_LEVEL > 1 + rtl::OString message = rtl::OUStringToOString(exception.Message, RTL_TEXTENCODING_ASCII_US); + OSL_TRACE("javavm.cxx: can not get locale cause of >%s<", message.getStr()); +#else + (void) exception; // unused +#endif + } + + try + { + getJavaPropsFromSafetySettings(&jvm, xSMgr, xCtx); + } + catch(css::uno::Exception & exception) { +#if OSL_DEBUG_LEVEL > 1 + rtl::OString message = rtl::OUStringToOString(exception.Message, RTL_TEXTENCODING_ASCII_US); + OSL_TRACE("javavm.cxx: couldn't get safety settings because of >%s<", message.getStr()); +#else + (void) exception; // unused +#endif + } + + *pjvm= jvm; + setTimeZone(pjvm); + +} + +class DetachCurrentThread { +public: + explicit DetachCurrentThread(JavaVM * jvm): m_jvm(jvm) {} + + ~DetachCurrentThread() { + if (m_jvm->DetachCurrentThread() != 0) { + OSL_ASSERT(false); + } + } + +private: + DetachCurrentThread(DetachCurrentThread &); // not defined + void operator =(DetachCurrentThread &); // not defined + + JavaVM * m_jvm; +}; + +} + +extern "C" void SAL_CALL +component_getImplementationEnvironment(sal_Char const ** pEnvTypeName, + uno_Environment **) +{ + *pEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +extern "C" void * SAL_CALL component_getFactory(sal_Char const * pImplName, + void * pServiceManager, + void * pRegistryKey) +{ + return cppu::component_getFactoryHelper(pImplName, pServiceManager, + pRegistryKey, + aServiceImplementation); +} + +// There is no component_canUnload, as the library cannot be unloaded. + +JavaVirtualMachine::JavaVirtualMachine( + css::uno::Reference< css::uno::XComponentContext > const & rContext): + JavaVirtualMachine_Impl(*static_cast< osl::Mutex * >(this)), + m_xContext(rContext), + m_bDisposed(false), + m_pJavaVm(0), + m_bDontCreateJvm(false), + m_aAttachGuards(destroyAttachGuards) // TODO check for validity +{} + +void SAL_CALL +JavaVirtualMachine::initialize(css::uno::Sequence< css::uno::Any > const & + rArguments) + throw (css::uno::Exception) +{ + osl::MutexGuard aGuard(*this); + if (m_bDisposed) + throw css::lang::DisposedException( + rtl::OUString(), static_cast< cppu::OWeakObject * >(this)); + if (m_xUnoVirtualMachine.is()) + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "bad call to initialize")), + static_cast< cppu::OWeakObject * >(this)); + css::beans::NamedValue val; + if (rArguments.getLength() == 1 && (rArguments[0] >>= val) + && val.Name.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM( "UnoVirtualMachine"))) + { + OSL_ENSURE( + sizeof (sal_Int64) >= sizeof (jvmaccess::UnoVirtualMachine *), + "Pointer cannot be represented as sal_Int64"); + sal_Int64 nPointer = reinterpret_cast< sal_Int64 >( + static_cast< jvmaccess::UnoVirtualMachine * >(0)); + val.Value >>= nPointer; + m_xUnoVirtualMachine = + reinterpret_cast< jvmaccess::UnoVirtualMachine * >(nPointer); + } else { + OSL_ENSURE( + sizeof (sal_Int64) >= sizeof (jvmaccess::VirtualMachine *), + "Pointer cannot be represented as sal_Int64"); + sal_Int64 nPointer = reinterpret_cast< sal_Int64 >( + static_cast< jvmaccess::VirtualMachine * >(0)); + if (rArguments.getLength() == 1) + rArguments[0] >>= nPointer; + rtl::Reference< jvmaccess::VirtualMachine > vm( + reinterpret_cast< jvmaccess::VirtualMachine * >(nPointer)); + if (vm.is()) { + try { + m_xUnoVirtualMachine = new jvmaccess::UnoVirtualMachine(vm, 0); + } catch (jvmaccess::UnoVirtualMachine::CreationException &) { + throw css::uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "jvmaccess::UnoVirtualMachine::CreationException")), + static_cast< cppu::OWeakObject * >(this)); + } + } + } + if (!m_xUnoVirtualMachine.is()) { + throw css::lang::IllegalArgumentException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "sequence of exactly one any containing either (a) a" + " com.sun.star.beans.NamedValue with Name" + " \"UnoVirtualMachine\" and Value a hyper representing a" + " non-null pointer to a jvmaccess:UnoVirtualMachine, or (b)" + " a hyper representing a non-null pointer to a" + " jvmaccess::VirtualMachine required")), + static_cast< cppu::OWeakObject * >(this), 0); + } + m_xVirtualMachine = m_xUnoVirtualMachine->getVirtualMachine(); +} + +rtl::OUString SAL_CALL JavaVirtualMachine::getImplementationName() + throw (css::uno::RuntimeException) +{ + return serviceGetImplementationName(); +} + +sal_Bool SAL_CALL +JavaVirtualMachine::supportsService(rtl::OUString const & rServiceName) + throw (css::uno::RuntimeException) +{ + css::uno::Sequence< rtl::OUString > aNames(getSupportedServiceNames()); + for (sal_Int32 i = 0; i < aNames.getLength(); ++i) + if (aNames[i] == rServiceName) + return true; + return false; +} + +css::uno::Sequence< rtl::OUString > SAL_CALL +JavaVirtualMachine::getSupportedServiceNames() + throw (css::uno::RuntimeException) +{ + return serviceGetSupportedServiceNames(); +} + +css::uno::Any SAL_CALL +JavaVirtualMachine::getJavaVM(css::uno::Sequence< sal_Int8 > const & rProcessId) + throw (css::uno::RuntimeException) +{ + osl::MutexGuard aGuard(*this); + if (m_bDisposed) + throw css::lang::DisposedException( + rtl::OUString(), static_cast< cppu::OWeakObject * >(this)); + css::uno::Sequence< sal_Int8 > aId(16); + rtl_getGlobalProcessId(reinterpret_cast< sal_uInt8 * >(aId.getArray())); + enum ReturnType { + RETURN_JAVAVM, RETURN_VIRTUALMACHINE, RETURN_UNOVIRTUALMACHINE }; + ReturnType returnType = + rProcessId.getLength() == 17 && rProcessId[16] == 0 + ? RETURN_VIRTUALMACHINE + : rProcessId.getLength() == 17 && rProcessId[16] == 1 + ? RETURN_UNOVIRTUALMACHINE + : RETURN_JAVAVM; + css::uno::Sequence< sal_Int8 > aProcessId(rProcessId); + if (returnType != RETURN_JAVAVM) + aProcessId.realloc(16); + if (aId != aProcessId) + return css::uno::Any(); + + while (!m_xVirtualMachine.is()) // retry until successful + { + // This is the second attempt to create Java. m_bDontCreateJvm is + // set which means instantiating the JVM might crash. + if (m_bDontCreateJvm) + //throw css::uno::RuntimeException(); + return css::uno::Any(); + + stoc_javavm::JVM aJvm; + initVMConfiguration(&aJvm, m_xContext->getServiceManager(), + m_xContext); + //Create the JavaVMOption array + const std::vector<rtl::OUString> & props = aJvm.getProperties(); + boost::scoped_array<JavaVMOption> sarOptions( + new JavaVMOption[props.size()]); + JavaVMOption * arOptions = sarOptions.get(); + //Create an array that contains the strings which are passed + //into the options + boost::scoped_array<rtl::OString> sarPropStrings( + new rtl::OString[props.size()]); + rtl::OString * arPropStrings = sarPropStrings.get(); + + rtl::OString sJavaOption("-"); + typedef std::vector<rtl::OUString>::const_iterator cit; + int index = 0; + for (cit i = props.begin(); i != props.end(); i++) + { + rtl::OString sOption = rtl::OUStringToOString( + *i, osl_getThreadTextEncoding()); + + if (!sOption.matchIgnoreAsciiCase(sJavaOption, 0)) + arPropStrings[index]= rtl::OString("-D") + sOption; + else + arPropStrings[index] = sOption; + + arOptions[index].optionString = (sal_Char*)arPropStrings[index].getStr(); + arOptions[index].extraInfo = 0; + index ++; + } + + JNIEnv * pMainThreadEnv = 0; + javaFrameworkError errcode = JFW_E_NONE; + errcode = jfw_startVM(arOptions, index, & m_pJavaVm, + & pMainThreadEnv); + + bool bStarted = false; + switch (errcode) + { + case JFW_E_NONE: bStarted = true; break; + case JFW_E_NO_SELECT: + { + // No Java configured. We silenty run the java configuration + // Java. + javaFrameworkError errFind = jfw_findAndSelectJRE( NULL ); + if (errFind == JFW_E_NONE) + { + continue; + } + else if (errFind == JFW_E_NO_JAVA_FOUND) + { + + //Warning MessageBox: + //%PRODUCTNAME requires a Java runtime environment (JRE) to perform this task. + //Please install a JRE and restart %PRODUCTNAME. + css::java::JavaNotFoundException exc( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "JavaVirtualMachine::getJavaVM failed because" + " No suitable JRE found!")), + static_cast< cppu::OWeakObject * >(this)); + askForRetry(css::uno::makeAny(exc)); + return css::uno::Any(); + } + else + { + //An unexpected error occurred + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "[JavaVirtualMachine]:An unexpected error occurred" + " while searching for a Java!")), 0); + } + } + case JFW_E_INVALID_SETTINGS: + { + //Warning MessageBox: + // The %PRODUCTNAME configuration has been changed. Under Tools + // - Options - %PRODUCTNAME - Java, select the Java runtime environment + // you want to have used by %PRODUCTNAME. + css::java::InvalidJavaSettingsException exc( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "JavaVirtualMachine::getJavaVM failed because" + " Java settings have changed!")), + static_cast< cppu::OWeakObject * >(this)); + askForRetry(css::uno::makeAny(exc)); + return css::uno::Any(); + } + case JFW_E_JAVA_DISABLED: + { + //QueryBox: + //%PRODUCTNAME requires a Java runtime environment (JRE) to perform + //this task. However, use of a JRE has been disabled. Do you want to + //enable the use of a JRE now? + css::java::JavaDisabledException exc( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "JavaVirtualMachine::getJavaVM failed because" + " Java is disabled!")), + static_cast< cppu::OWeakObject * >(this)); + if( ! askForRetry(css::uno::makeAny(exc))) + return css::uno::Any(); + continue; + } + case JFW_E_VM_CREATION_FAILED: + { + //If the creation failed because the JRE has been uninstalled then + //we search another one. As long as there is a javaldx, we should + //never come into this situation. javaldx checks alway if the JRE + //still exist. + JavaInfo * pJavaInfo = NULL; + if (JFW_E_NONE == jfw_getSelectedJRE(&pJavaInfo)) + { + sal_Bool bExist = sal_False; + if (JFW_E_NONE == jfw_existJRE(pJavaInfo, &bExist)) + { + if (bExist == sal_False + && ! (pJavaInfo->nRequirements & JFW_REQUIRE_NEEDRESTART)) + { + javaFrameworkError errFind = jfw_findAndSelectJRE( NULL ); + if (errFind == JFW_E_NONE) + { + continue; + } + } + } + } + + jfw_freeJavaInfo(pJavaInfo); + // + //Error: %PRODUCTNAME requires a Java + //runtime environment (JRE) to perform this task. The selected JRE + //is defective. Please select another version or install a new JRE + //and select it under Tools - Options - %PRODUCTNAME - Java. + css::java::JavaVMCreationFailureException exc( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "JavaVirtualMachine::getJavaVM failed because" + " Java is defective!")), + static_cast< cppu::OWeakObject * >(this), 0); + askForRetry(css::uno::makeAny(exc)); + return css::uno::Any(); + } + case JFW_E_RUNNING_JVM: + { + //This service should make sure that we do not start java twice. + OSL_ASSERT(0); + break; + } + case JFW_E_NEED_RESTART: + { + //Error: + //For the selected Java runtime environment to work properly, + //%PRODUCTNAME must be restarted. Please restart %PRODUCTNAME now. + css::java::RestartRequiredException exc( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "JavaVirtualMachine::getJavaVM failed because" + "Office must be restarted before Java can be used!")), + static_cast< cppu::OWeakObject * >(this)); + askForRetry(css::uno::makeAny(exc)); + return css::uno::Any(); + } + default: + //RuntimeException: error is somewhere in the java framework. + //An unexpected error occurred + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "[JavaVirtualMachine]:An unexpected error occurred" + " while starting Java!")), 0); + } + + if (bStarted) + { + { + DetachCurrentThread detach(m_pJavaVm); + // necessary to make debugging work; this thread will be + // suspended when the destructor of detach returns + m_xVirtualMachine = new jvmaccess::VirtualMachine( + m_pJavaVm, JNI_VERSION_1_2, true, pMainThreadEnv); + setUpUnoVirtualMachine(pMainThreadEnv); + } + // Listen for changes in the configuration (e.g. proxy settings): + // TODO this is done too late; changes to the configuration done + // after the above call to initVMConfiguration are lost + registerConfigChangesListener(); + + break; + } + } + if (!m_xUnoVirtualMachine.is()) { + try { + jvmaccess::VirtualMachine::AttachGuard guard(m_xVirtualMachine); + setUpUnoVirtualMachine(guard.getEnvironment()); + } catch (jvmaccess::VirtualMachine::AttachGuard::CreationException &) { + throw css::uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "jvmaccess::VirtualMachine::AttachGuard::" + "CreationException occurred")), + static_cast< cppu::OWeakObject * >(this)); + } + } + switch (returnType) { + default: // RETURN_JAVAVM + if (m_pJavaVm == 0) { + throw css::uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "JavaVirtualMachine service was initialized in a way" + " that the requested JavaVM pointer is not available")), + static_cast< cppu::OWeakObject * >(this)); + } + return css::uno::makeAny(reinterpret_cast< sal_IntPtr >(m_pJavaVm)); + case RETURN_VIRTUALMACHINE: + OSL_ASSERT(sizeof (sal_Int64) >= sizeof (jvmaccess::VirtualMachine *)); + return css::uno::makeAny( + reinterpret_cast< sal_Int64 >( + m_xUnoVirtualMachine->getVirtualMachine().get())); + case RETURN_UNOVIRTUALMACHINE: + OSL_ASSERT(sizeof (sal_Int64) >= sizeof (jvmaccess::VirtualMachine *)); + return css::uno::makeAny( + reinterpret_cast< sal_Int64 >(m_xUnoVirtualMachine.get())); + } +} + +sal_Bool SAL_CALL JavaVirtualMachine::isVMStarted() + throw (css::uno::RuntimeException) +{ + osl::MutexGuard aGuard(*this); + if (m_bDisposed) + throw css::lang::DisposedException( + rtl::OUString(), static_cast< cppu::OWeakObject * >(this)); + return m_xUnoVirtualMachine.is(); +} + +sal_Bool SAL_CALL JavaVirtualMachine::isVMEnabled() + throw (css::uno::RuntimeException) +{ + { + osl::MutexGuard aGuard(*this); + if (m_bDisposed) + throw css::lang::DisposedException( + rtl::OUString(), static_cast< cppu::OWeakObject * >(this)); + } +// stoc_javavm::JVM aJvm; +// initVMConfiguration(&aJvm, m_xContext->getServiceManager(), m_xContext); +// return aJvm.isEnabled(); + //ToDo + sal_Bool bEnabled = sal_False; + if (jfw_getEnabled( & bEnabled) != JFW_E_NONE) + throw css::uno::RuntimeException(); + return bEnabled; +} + +sal_Bool SAL_CALL JavaVirtualMachine::isThreadAttached() + throw (css::uno::RuntimeException) +{ + osl::MutexGuard aGuard(*this); + if (m_bDisposed) + throw css::lang::DisposedException( + rtl::OUString(), static_cast< cppu::OWeakObject * >(this)); + // TODO isThreadAttached only returns true if the thread was attached via + // registerThread: + GuardStack * pStack + = static_cast< GuardStack * >(m_aAttachGuards.getData()); + return pStack != 0 && !pStack->empty(); +} + +void SAL_CALL JavaVirtualMachine::registerThread() + throw (css::uno::RuntimeException) +{ + osl::MutexGuard aGuard(*this); + if (m_bDisposed) + throw css::lang::DisposedException( + rtl::OUString(), static_cast< cppu::OWeakObject * >(this)); + if (!m_xUnoVirtualMachine.is()) + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "JavaVirtualMachine::registerThread:" + " null VirtualMachine")), + static_cast< cppu::OWeakObject * >(this)); + GuardStack * pStack + = static_cast< GuardStack * >(m_aAttachGuards.getData()); + if (pStack == 0) + { + pStack = new GuardStack; + m_aAttachGuards.setData(pStack); + } + try + { + pStack->push( + new jvmaccess::VirtualMachine::AttachGuard( + m_xUnoVirtualMachine->getVirtualMachine())); + } + catch (jvmaccess::VirtualMachine::AttachGuard::CreationException &) + { + throw css::uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "JavaVirtualMachine::registerThread: jvmaccess::" + "VirtualMachine::AttachGuard::CreationException")), + static_cast< cppu::OWeakObject * >(this)); + } +} + +void SAL_CALL JavaVirtualMachine::revokeThread() + throw (css::uno::RuntimeException) +{ + osl::MutexGuard aGuard(*this); + if (m_bDisposed) + throw css::lang::DisposedException( + rtl::OUString(), static_cast< cppu::OWeakObject * >(this)); + if (!m_xUnoVirtualMachine.is()) + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "JavaVirtualMachine::revokeThread:" + " null VirtualMachine")), + static_cast< cppu::OWeakObject * >(this)); + GuardStack * pStack + = static_cast< GuardStack * >(m_aAttachGuards.getData()); + if (pStack == 0 || pStack->empty()) + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "JavaVirtualMachine::revokeThread:" + " no matching registerThread")), + static_cast< cppu::OWeakObject * >(this)); + delete pStack->top(); + pStack->pop(); +} + +void SAL_CALL +JavaVirtualMachine::disposing(css::lang::EventObject const & rSource) + throw (css::uno::RuntimeException) +{ + osl::MutexGuard aGuard(*this); + if (rSource.Source == m_xInetConfiguration) + m_xInetConfiguration.clear(); + if (rSource.Source == m_xJavaConfiguration) + m_xJavaConfiguration.clear(); +} + +void SAL_CALL JavaVirtualMachine::elementInserted( + css::container::ContainerEvent const &) + throw (css::uno::RuntimeException) +{} + +void SAL_CALL JavaVirtualMachine::elementRemoved( + css::container::ContainerEvent const &) + throw (css::uno::RuntimeException) +{} + +// If a user changes the setting, for example for proxy settings, then this +// function will be called from the configuration manager. Even if the .xml +// file does not contain an entry yet and that entry has to be inserted, this +// function will be called. We call java.lang.System.setProperty for the new +// values. +void SAL_CALL JavaVirtualMachine::elementReplaced( + css::container::ContainerEvent const & rEvent) + throw (css::uno::RuntimeException) +{ + // TODO Using the new value stored in rEvent is wrong here. If two threads + // receive different elementReplaced calls in quick succession, it is + // unspecified which changes the JVM's system properties last. A correct + // solution must atomically (i.e., protected by a mutex) read the latest + // value from the configuration and set it as a system property at the JVM. + + rtl::OUString aAccessor; + rEvent.Accessor >>= aAccessor; + rtl::OUString aPropertyName; + rtl::OUString aPropertyName2; + rtl::OUString aPropertyValue; + bool bSecurityChanged = false; + if (aAccessor.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("ooInetProxyType"))) + { + // Proxy none, manually + sal_Int32 value = 0; + rEvent.Element >>= value; + setINetSettingsInVM(value != 0); + return; + } + else if (aAccessor.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( + "ooInetHTTPProxyName"))) + { + aPropertyName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "http.proxyHost")); + rEvent.Element >>= aPropertyValue; + } + else if (aAccessor.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( + "ooInetHTTPProxyPort"))) + { + aPropertyName + = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("http.proxyPort")); + sal_Int32 n = 0; + rEvent.Element >>= n; + aPropertyValue = rtl::OUString::valueOf(n); + } + else if (aAccessor.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( + "ooInetHTTPSProxyName"))) + { + aPropertyName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "https.proxyHost")); + rEvent.Element >>= aPropertyValue; + } + else if (aAccessor.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( + "ooInetHTTPSProxyPort"))) + { + aPropertyName + = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("https.proxyPort")); + sal_Int32 n = 0; + rEvent.Element >>= n; + aPropertyValue = rtl::OUString::valueOf(n); + } + else if (aAccessor.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( + "ooInetFTPProxyName"))) + { + aPropertyName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "ftp.proxyHost")); + rEvent.Element >>= aPropertyValue; + } + else if (aAccessor.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( + "ooInetFTPProxyPort"))) + { + aPropertyName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "ftp.proxyPort")); + sal_Int32 n = 0; + rEvent.Element >>= n; + aPropertyValue = rtl::OUString::valueOf(n); + } + else if (aAccessor.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( + "ooInetNoProxy"))) + { + aPropertyName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "http.nonProxyHosts")); + aPropertyName2 = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "ftp.nonProxyHosts")); + rEvent.Element >>= aPropertyValue; + aPropertyValue = aPropertyValue.replace(';', '|'); + } + else if (aAccessor.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("NetAccess"))) + { + aPropertyName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "appletviewer.security.mode")); + sal_Int32 n = 0; + if (rEvent.Element >>= n) + switch (n) + { + case 0: + aPropertyValue = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "host")); + break; + case 1: + aPropertyValue = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "unrestricted")); + break; + case 3: + aPropertyValue = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "none")); + break; + } + else + return; + bSecurityChanged = true; + } + else if (aAccessor.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Security"))) + { + aPropertyName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "stardiv.security.disableSecurity")); + sal_Bool b = sal_Bool(); + if (rEvent.Element >>= b) + if (b) + aPropertyValue = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "false")); + else + aPropertyValue = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "true")); + else + return; + bSecurityChanged = true; + } + else + return; + + rtl::Reference< jvmaccess::VirtualMachine > xVirtualMachine; + { + osl::MutexGuard aGuard(*this); + if (m_xUnoVirtualMachine.is()) { + xVirtualMachine = m_xUnoVirtualMachine->getVirtualMachine(); + } + } + if (xVirtualMachine.is()) + { + try + { + jvmaccess::VirtualMachine::AttachGuard aAttachGuard( + xVirtualMachine); + JNIEnv * pJNIEnv = aAttachGuard.getEnvironment(); + + // call java.lang.System.setProperty + // String setProperty( String key, String value) + jclass jcSystem= pJNIEnv->FindClass("java/lang/System"); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:FindClass java/lang/System")), 0); + jmethodID jmSetProps= pJNIEnv->GetStaticMethodID( jcSystem, "setProperty","(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:GetStaticMethodID java.lang.System.setProperty")), 0); + + jstring jsPropName= pJNIEnv->NewString( aPropertyName.getStr(), aPropertyName.getLength()); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:NewString")), 0); + + // remove the property if it does not have a value ( user left the dialog field empty) + // or if the port is set to 0 + aPropertyValue= aPropertyValue.trim(); + if( + aPropertyValue.getLength() == 0 || + ( + ( + aPropertyName.equals( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ftp.proxyPort"))) || + aPropertyName.equals( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("http.proxyPort"))) /*|| + aPropertyName.equals( OUString( RTL_CONSTASCII_USTRINGPARAM("socksProxyPort")))*/ + ) && + aPropertyValue.equals(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("0"))) + ) + ) + { + // call java.lang.System.getProperties + jmethodID jmGetProps= pJNIEnv->GetStaticMethodID( jcSystem, "getProperties","()Ljava/util/Properties;"); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:GetStaticMethodID java.lang.System.getProperties")), 0); + jobject joProperties= pJNIEnv->CallStaticObjectMethod( jcSystem, jmGetProps); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:CallStaticObjectMethod java.lang.System.getProperties")), 0); + // call java.util.Properties.remove + jclass jcProperties= pJNIEnv->FindClass("java/util/Properties"); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:FindClass java/util/Properties")), 0); + jmethodID jmRemove= pJNIEnv->GetMethodID( jcProperties, "remove", "(Ljava/lang/Object;)Ljava/lang/Object;"); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:GetMethodID java.util.Properties.remove")), 0); + pJNIEnv->CallObjectMethod( joProperties, jmRemove, jsPropName); + + // special calse for ftp.nonProxyHosts and http.nonProxyHosts. The office only + // has a value for two java properties + if (aPropertyName2.getLength() > 0) + { + jstring jsPropName2= pJNIEnv->NewString( aPropertyName2.getStr(), aPropertyName2.getLength()); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:NewString")), 0); + pJNIEnv->CallObjectMethod( joProperties, jmRemove, jsPropName2); + } + } + else + { + // Change the Value of the property + jstring jsPropValue= pJNIEnv->NewString( aPropertyValue.getStr(), aPropertyValue.getLength()); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:NewString")), 0); + pJNIEnv->CallStaticObjectMethod( jcSystem, jmSetProps, jsPropName, jsPropValue); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:CallStaticObjectMethod java.lang.System.setProperty")), 0); + + // special calse for ftp.nonProxyHosts and http.nonProxyHosts. The office only + // has a value for two java properties + if (aPropertyName2.getLength() > 0) + { + jstring jsPropName2= pJNIEnv->NewString( aPropertyName2.getStr(), aPropertyName2.getLength()); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:NewString")), 0); + jsPropValue= pJNIEnv->NewString( aPropertyValue.getStr(), aPropertyValue.getLength()); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:NewString")), 0); + pJNIEnv->CallStaticObjectMethod( jcSystem, jmSetProps, jsPropName2, jsPropValue); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:CallStaticObjectMethod java.lang.System.setProperty")), 0); + } + } + + // If the settings for Security and NetAccess changed then we have to notify the SandboxSecurity + // SecurityManager + // call System.getSecurityManager() + if (bSecurityChanged) + { + jmethodID jmGetSecur= pJNIEnv->GetStaticMethodID( jcSystem,"getSecurityManager","()Ljava/lang/SecurityManager;"); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:GetStaticMethodID java.lang.System.getSecurityManager")), 0); + jobject joSecur= pJNIEnv->CallStaticObjectMethod( jcSystem, jmGetSecur); + if (joSecur != 0) + { + // Make sure the SecurityManager is our SandboxSecurity + // FindClass("com.sun.star.lib.sandbox.SandboxSecurityManager" only worked at the first time + // this code was executed. Maybe it is a security feature. However, all attempts to debug the + // SandboxSecurity class (maybe the VM invokes checkPackageAccess) failed. +// jclass jcSandboxSec= pJNIEnv->FindClass("com.sun.star.lib.sandbox.SandboxSecurity"); +// if(pJNIEnv->ExceptionOccurred()) throw RuntimeException(OUSTR("JNI:FindClass com.sun.star.lib.sandbox.SandboxSecurity"), Reference<XInterface>()); +// jboolean bIsSand= pJNIEnv->IsInstanceOf( joSecur, jcSandboxSec); + // The SecurityManagers class Name must be com.sun.star.lib.sandbox.SandboxSecurity + jclass jcSec= pJNIEnv->GetObjectClass( joSecur); + jclass jcClass= pJNIEnv->FindClass("java/lang/Class"); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:FindClass java.lang.Class")), 0); + jmethodID jmName= pJNIEnv->GetMethodID( jcClass,"getName","()Ljava/lang/String;"); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:GetMethodID java.lang.Class.getName")), 0); + jstring jsClass= (jstring) pJNIEnv->CallObjectMethod( jcSec, jmName); + const jchar* jcharName= pJNIEnv->GetStringChars( jsClass, NULL); + rtl::OUString sName( jcharName); + jboolean bIsSandbox; + if (sName == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lib.sandbox.SandboxSecurity"))) + bIsSandbox= JNI_TRUE; + else + bIsSandbox= JNI_FALSE; + pJNIEnv->ReleaseStringChars( jsClass, jcharName); + + if (bIsSandbox == JNI_TRUE) + { + // call SandboxSecurity.reset + jmethodID jmReset= pJNIEnv->GetMethodID( jcSec,"reset","()V"); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:GetMethodID com.sun.star.lib.sandbox.SandboxSecurity.reset")), 0); + pJNIEnv->CallVoidMethod( joSecur, jmReset); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:CallVoidMethod com.sun.star.lib.sandbox.SandboxSecurity.reset")), 0); + } + } + } + } + catch (jvmaccess::VirtualMachine::AttachGuard::CreationException &) + { + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "jvmaccess::VirtualMachine::AttachGuard::" + "CreationException")), + 0); + } + } +} + +JavaVirtualMachine::~JavaVirtualMachine() +{ + if (m_xInetConfiguration.is()) + // We should never get here, but just in case... + try + { + m_xInetConfiguration->removeContainerListener(this); + } + catch (css::uno::Exception &) + { + OSL_ENSURE(false, "com.sun.star.uno.Exception caught"); + } + if (m_xJavaConfiguration.is()) + // We should never get here, but just in case... + try + { + m_xJavaConfiguration->removeContainerListener(this); + } + catch (css::uno::Exception &) + { + OSL_ENSURE(false, "com.sun.star.uno.Exception caught"); + } +} + +void SAL_CALL JavaVirtualMachine::disposing() +{ + css::uno::Reference< css::container::XContainer > xContainer1; + css::uno::Reference< css::container::XContainer > xContainer2; + { + osl::MutexGuard aGuard(*this); + m_bDisposed = true; + xContainer1 = m_xInetConfiguration; + m_xInetConfiguration.clear(); + xContainer2 = m_xJavaConfiguration; + m_xJavaConfiguration.clear(); + } + if (xContainer1.is()) + xContainer1->removeContainerListener(this); + if (xContainer2.is()) + xContainer2->removeContainerListener(this); +} + +/*We listen to changes in the configuration. For example, the user changes the proxy + settings in the options dialog (menu tools). Then we are notified of this change and + if the java vm is already running we change the properties (System.lang.System.setProperties) + through JNI. + To receive notifications this class implements XContainerListener. +*/ +void JavaVirtualMachine::registerConfigChangesListener() +{ + try + { + css::uno::Reference< css::lang::XMultiServiceFactory > xConfigProvider( + m_xContext->getServiceManager()->createInstanceWithContext( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.ConfigurationProvider")), m_xContext), css::uno::UNO_QUERY); + + if (xConfigProvider.is()) + { + // We register this instance as listener to changes in org.openoffice.Inet/Settings + // arguments for ConfigurationAccess + css::uno::Sequence< css::uno::Any > aArguments(2); + aArguments[0] <<= css::beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("nodepath")), + 0, + css::uno::makeAny(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Inet/Settings"))), + css::beans::PropertyState_DIRECT_VALUE); + // depth: -1 means unlimited + aArguments[1] <<= css::beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("depth")), + 0, + css::uno::makeAny( (sal_Int32)-1), + css::beans::PropertyState_DIRECT_VALUE); + + m_xInetConfiguration + = css::uno::Reference< css::container::XContainer >( + xConfigProvider->createInstanceWithArguments( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.ConfigurationAccess")), + aArguments), + css::uno::UNO_QUERY); + + if (m_xInetConfiguration.is()) + m_xInetConfiguration->addContainerListener(this); + + // now register as listener to changes in org.openoffice.Java/VirtualMachine + css::uno::Sequence< css::uno::Any > aArguments2(2); + aArguments2[0] <<= css::beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("nodepath")), + 0, + css::uno::makeAny(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Java/VirtualMachine"))), + css::beans::PropertyState_DIRECT_VALUE); + // depth: -1 means unlimited + aArguments2[1] <<= css::beans::PropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("depth")), + 0, + css::uno::makeAny( (sal_Int32)-1), + css::beans::PropertyState_DIRECT_VALUE); + + m_xJavaConfiguration + = css::uno::Reference< css::container::XContainer >( + xConfigProvider->createInstanceWithArguments( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.configuration.ConfigurationAccess")), + aArguments2), + css::uno::UNO_QUERY); + + if (m_xJavaConfiguration.is()) + m_xJavaConfiguration->addContainerListener(this); + } + }catch( css::uno::Exception & e) + { +#if OSL_DEBUG_LEVEL > 1 + rtl::OString message = rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US); + OSL_TRACE("javavm.cxx: could not set up listener for Configuration because of >%s<", message.getStr()); +#else + (void) e; // unused +#endif + } +} + +// param true: all Inet setting are set as Java Properties on a live VM. +// false: the Java net properties are set to empty value. +void JavaVirtualMachine::setINetSettingsInVM(bool set_reset) +{ + osl::MutexGuard aGuard(*this); + try + { + if (m_xUnoVirtualMachine.is()) + { + jvmaccess::VirtualMachine::AttachGuard aAttachGuard( + m_xUnoVirtualMachine->getVirtualMachine()); + JNIEnv * pJNIEnv = aAttachGuard.getEnvironment(); + + // The Java Properties + rtl::OUString sFtpProxyHost(RTL_CONSTASCII_USTRINGPARAM("ftp.proxyHost") ); + rtl::OUString sFtpProxyPort(RTL_CONSTASCII_USTRINGPARAM("ftp.proxyPort") ); + rtl::OUString sFtpNonProxyHosts (RTL_CONSTASCII_USTRINGPARAM("ftp.nonProxyHosts")); + rtl::OUString sHttpProxyHost(RTL_CONSTASCII_USTRINGPARAM("http.proxyHost") ); + rtl::OUString sHttpProxyPort(RTL_CONSTASCII_USTRINGPARAM("http.proxyPort") ); + rtl::OUString sHttpNonProxyHosts(RTL_CONSTASCII_USTRINGPARAM("http.nonProxyHosts")); + + // creat Java Properties as JNI strings + jstring jsFtpProxyHost= pJNIEnv->NewString( sFtpProxyHost.getStr(), sFtpProxyHost.getLength()); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:NewString")), 0); + jstring jsFtpProxyPort= pJNIEnv->NewString( sFtpProxyPort.getStr(), sFtpProxyPort.getLength()); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:NewString")), 0); + jstring jsFtpNonProxyHosts= pJNIEnv->NewString( sFtpNonProxyHosts.getStr(), sFtpNonProxyHosts.getLength()); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:NewString")), 0); + jstring jsHttpProxyHost= pJNIEnv->NewString( sHttpProxyHost.getStr(), sHttpProxyHost.getLength()); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:NewString")), 0); + jstring jsHttpProxyPort= pJNIEnv->NewString( sHttpProxyPort.getStr(), sHttpProxyPort.getLength()); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:NewString")), 0); + jstring jsHttpNonProxyHosts= pJNIEnv->NewString( sHttpNonProxyHosts.getStr(), sHttpNonProxyHosts.getLength()); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:NewString")), 0); + + // prepare java.lang.System.setProperty + jclass jcSystem= pJNIEnv->FindClass("java/lang/System"); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:FindClass java/lang/System")), 0); + jmethodID jmSetProps= pJNIEnv->GetStaticMethodID( jcSystem, "setProperty","(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:GetStaticMethodID java.lang.System.setProperty")), 0); + + // call java.lang.System.getProperties + jmethodID jmGetProps= pJNIEnv->GetStaticMethodID( jcSystem, "getProperties","()Ljava/util/Properties;"); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:GetStaticMethodID java.lang.System.getProperties")), 0); + jobject joProperties= pJNIEnv->CallStaticObjectMethod( jcSystem, jmGetProps); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:CallStaticObjectMethod java.lang.System.getProperties")), 0); + // prepare java.util.Properties.remove + jclass jcProperties= pJNIEnv->FindClass("java/util/Properties"); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:FindClass java/util/Properties")), 0); + + if (set_reset) + { + // Set all network properties with the VM + JVM jvm; + getINetPropsFromConfig( &jvm, m_xContext->getServiceManager(), m_xContext); + const ::std::vector< rtl::OUString> & Props = jvm.getProperties(); + typedef ::std::vector< rtl::OUString >::const_iterator C_IT; + + for( C_IT i= Props.begin(); i != Props.end(); i++) + { + rtl::OUString prop= *i; + sal_Int32 index= prop.indexOf( (sal_Unicode)'='); + rtl::OUString propName= prop.copy( 0, index); + rtl::OUString propValue= prop.copy( index + 1); + + if( propName.equals( sFtpProxyHost)) + { + jstring jsVal= pJNIEnv->NewString( propValue.getStr(), propValue.getLength()); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:NewString")), 0); + pJNIEnv->CallStaticObjectMethod( jcSystem, jmSetProps, jsFtpProxyHost, jsVal); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:CallStaticObjectMethod java.lang.System.setProperty")), 0); + } + else if( propName.equals( sFtpProxyPort)) + { + jstring jsVal= pJNIEnv->NewString( propValue.getStr(), propValue.getLength()); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:NewString")), 0); + pJNIEnv->CallStaticObjectMethod( jcSystem, jmSetProps, jsFtpProxyPort, jsVal); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:CallStaticObjectMethod java.lang.System.setProperty")), 0); + } + else if( propName.equals( sFtpNonProxyHosts)) + { + jstring jsVal= pJNIEnv->NewString( propValue.getStr(), propValue.getLength()); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:NewString")), 0); + pJNIEnv->CallStaticObjectMethod( jcSystem, jmSetProps, jsFtpNonProxyHosts, jsVal); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:CallStaticObjectMethod java.lang.System.setProperty")), 0); + } + else if( propName.equals( sHttpProxyHost)) + { + jstring jsVal= pJNIEnv->NewString( propValue.getStr(), propValue.getLength()); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:NewString")), 0); + pJNIEnv->CallStaticObjectMethod( jcSystem, jmSetProps, jsHttpProxyHost, jsVal); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:CallStaticObjectMethod java.lang.System.setProperty")), 0); + } + else if( propName.equals( sHttpProxyPort)) + { + jstring jsVal= pJNIEnv->NewString( propValue.getStr(), propValue.getLength()); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:NewString")), 0); + pJNIEnv->CallStaticObjectMethod( jcSystem, jmSetProps, jsHttpProxyPort, jsVal); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:CallStaticObjectMethod java.lang.System.setProperty")), 0); + } + else if( propName.equals( sHttpNonProxyHosts)) + { + jstring jsVal= pJNIEnv->NewString( propValue.getStr(), propValue.getLength()); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:NewString")), 0); + pJNIEnv->CallStaticObjectMethod( jcSystem, jmSetProps, jsHttpNonProxyHosts, jsVal); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:CallStaticObjectMethod java.lang.System.setProperty")), 0); + } + } + } + else + { + // call java.util.Properties.remove + jmethodID jmRemove= pJNIEnv->GetMethodID( jcProperties, "remove", "(Ljava/lang/Object;)Ljava/lang/Object;"); + if(pJNIEnv->ExceptionOccurred()) throw css::uno::RuntimeException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("JNI:GetMethodID java.util.Property.remove")), 0); + pJNIEnv->CallObjectMethod( joProperties, jmRemove, jsFtpProxyHost); + pJNIEnv->CallObjectMethod( joProperties, jmRemove, jsFtpProxyPort); + pJNIEnv->CallObjectMethod( joProperties, jmRemove, jsFtpNonProxyHosts); + pJNIEnv->CallObjectMethod( joProperties, jmRemove, jsHttpProxyHost); + pJNIEnv->CallObjectMethod( joProperties, jmRemove, jsHttpProxyPort); + pJNIEnv->CallObjectMethod( joProperties, jmRemove, jsHttpNonProxyHosts); + } + } + } + catch (css::uno::RuntimeException &) + { + OSL_ENSURE(false, "RuntimeException"); + } + catch (jvmaccess::VirtualMachine::AttachGuard::CreationException &) + { + OSL_ENSURE(false, + "jvmaccess::VirtualMachine::AttachGuard::CreationException"); + } +} + +void JavaVirtualMachine::setUpUnoVirtualMachine(JNIEnv * environment) { + css::uno::Reference< css::util::XMacroExpander > exp; + if (!(m_xContext->getValueByName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "/singletons/com.sun.star.util.theMacroExpander"))) + >>= exp) + || !exp.is()) + { + throw css::uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "component context fails to supply singleton" + " com.sun.star.util.theMacroExpander of type" + " com.sun.star.util.XMacroExpander")), + m_xContext); + } + rtl::OUString baseUrl; + try { + baseUrl = exp->expandMacros( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("$URE_INTERNAL_JAVA_DIR/"))); + } catch (css::lang::IllegalArgumentException &) { + throw css::uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com::sun::star::lang::IllegalArgumentException")), + static_cast< cppu::OWeakObject * >(this)); + } + rtl::OUString classPath; + try { + classPath = exp->expandMacros( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("$URE_INTERNAL_JAVA_CLASSPATH"))); + } catch (css::lang::IllegalArgumentException &) {} + jclass class_URLClassLoader = environment->FindClass( + "java/net/URLClassLoader"); + if (class_URLClassLoader == 0) { + handleJniException(environment); + } + jmethodID ctor_URLClassLoader = environment->GetMethodID( + class_URLClassLoader, "<init>", "([Ljava/net/URL;)V"); + if (ctor_URLClassLoader == 0) { + handleJniException(environment); + } + jclass class_URL = environment->FindClass("java/net/URL"); + if (class_URL == 0) { + handleJniException(environment); + } + jmethodID ctor_URL_1 = environment->GetMethodID( + class_URL, "<init>", "(Ljava/lang/String;)V"); + if (ctor_URL_1 == 0) { + handleJniException(environment); + } + jvalue args[3]; + args[0].l = environment->NewString( + static_cast< jchar const * >(baseUrl.getStr()), + static_cast< jsize >(baseUrl.getLength())); + if (args[0].l == 0) { + handleJniException(environment); + } + jobject base = environment->NewObjectA(class_URL, ctor_URL_1, args); + if (base == 0) { + handleJniException(environment); + } + jmethodID ctor_URL_2 = environment->GetMethodID( + class_URL, "<init>", "(Ljava/net/URL;Ljava/lang/String;)V"); + if (ctor_URL_2 == 0) { + handleJniException(environment); + } + jobjectArray classpath = jvmaccess::ClassPath::translateToUrls( + m_xContext, environment, classPath); + if (classpath == 0) { + handleJniException(environment); + } + args[0].l = base; + args[1].l = environment->NewStringUTF("unoloader.jar"); + if (args[1].l == 0) { + handleJniException(environment); + } + args[0].l = environment->NewObjectA(class_URL, ctor_URL_2, args); + if (args[0].l == 0) { + handleJniException(environment); + } + args[0].l = environment->NewObjectArray(1, class_URL, args[0].l); + if (args[0].l == 0) { + handleJniException(environment); + } + jobject cl1 = environment->NewObjectA( + class_URLClassLoader, ctor_URLClassLoader, args); + if (cl1 == 0) { + handleJniException(environment); + } + jmethodID method_loadClass = environment->GetMethodID( + class_URLClassLoader, "loadClass", + "(Ljava/lang/String;)Ljava/lang/Class;"); + if (method_loadClass == 0) { + handleJniException(environment); + } + args[0].l = environment->NewStringUTF( + "com.sun.star.lib.unoloader.UnoClassLoader"); + if (args[0].l == 0) { + handleJniException(environment); + } + jclass class_UnoClassLoader = static_cast< jclass >( + environment->CallObjectMethodA(cl1, method_loadClass, args)); + if (class_UnoClassLoader == 0) { + handleJniException(environment); + } + jmethodID ctor_UnoClassLoader = environment->GetMethodID( + class_UnoClassLoader, "<init>", + "(Ljava/net/URL;[Ljava/net/URL;Ljava/lang/ClassLoader;)V"); + if (ctor_UnoClassLoader == 0) { + handleJniException(environment); + } + args[0].l = base; + args[1].l = classpath; + args[2].l = cl1; + jobject cl2 = environment->NewObjectA( + class_UnoClassLoader, ctor_UnoClassLoader, args); + if (cl2 == 0) { + handleJniException(environment); + } + try { + m_xUnoVirtualMachine = new jvmaccess::UnoVirtualMachine( + m_xVirtualMachine, cl2); + } catch (jvmaccess::UnoVirtualMachine::CreationException &) { + throw css::uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "jvmaccess::UnoVirtualMachine::CreationException")), + static_cast< cppu::OWeakObject * >(this)); + } +} + +void JavaVirtualMachine::handleJniException(JNIEnv * environment) { + environment->ExceptionClear(); + throw css::uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("JNI exception occurred")), + static_cast< cppu::OWeakObject * >(this)); +} diff --git a/stoc/source/javavm/javavm.hxx b/stoc/source/javavm/javavm.hxx new file mode 100644 index 000000000000..d04ed4a2805c --- /dev/null +++ b/stoc/source/javavm/javavm.hxx @@ -0,0 +1,172 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#if !defined INCLUDED_STOC_JAVAVM_JAVAVM_HXX +#define INCLUDED_STOC_JAVAVM_JAVAVM_HXX + +#include "jvmargs.hxx" + +#include "com/sun/star/container/XContainerListener.hpp" +#include "com/sun/star/lang/XInitialization.hpp" +#include "com/sun/star/java/XJavaThreadRegister_11.hpp" +#include "com/sun/star/java/XJavaVM.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "cppuhelper/compbase5.hxx" +#include "osl/thread.hxx" +#include "rtl/ref.hxx" +#include <osl/mutex.hxx> +#include <rtl/ustring.hxx> + +namespace com { namespace sun { namespace star { + namespace container { class XContainer; } + namespace uno { class XComponentContext; } +} } } +namespace jvmaccess { + class UnoVirtualMachine; + class VirtualMachine; +} + +namespace stoc_javavm { + +bool configureJava(const com::sun::star::uno::Reference< + com::sun::star::uno::XComponentContext>& xContext); +// The MS compiler needs a typedef here, so the JavaVirtualMachine ctor can call +// its base class ctor: +typedef +cppu::WeakComponentImplHelper5< com::sun::star::lang::XInitialization, + com::sun::star::lang::XServiceInfo, + com::sun::star::java::XJavaVM, + com::sun::star::java::XJavaThreadRegister_11, + com::sun::star::container::XContainerListener > +JavaVirtualMachine_Impl; + +class JavaVirtualMachine: private osl::Mutex, public JavaVirtualMachine_Impl +{ +public: + explicit JavaVirtualMachine( + com::sun::star::uno::Reference< + com::sun::star::uno::XComponentContext > const & rContext); + + // XInitialization + virtual void SAL_CALL + initialize(com::sun::star::uno::Sequence< com::sun::star::uno::Any > const & + rArguments) + throw (com::sun::star::uno::Exception); + + // XServiceInfo + virtual rtl::OUString SAL_CALL getImplementationName() + throw (com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL + supportsService(rtl::OUString const & rServiceName) + throw (com::sun::star::uno::RuntimeException); + + virtual com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames() throw (com::sun::star::uno::RuntimeException); + + // XJavaVM + virtual com::sun::star::uno::Any SAL_CALL + getJavaVM(com::sun::star::uno::Sequence< sal_Int8 > const & rProcessId) + throw (com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isVMStarted() + throw (com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isVMEnabled() + throw (com::sun::star::uno::RuntimeException); + + // XJavaThreadRegister_11 + virtual sal_Bool SAL_CALL isThreadAttached() + throw (com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL registerThread() + throw (com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL revokeThread() + throw (com::sun::star::uno::RuntimeException); + + // XContainerListener + virtual void SAL_CALL + disposing(com::sun::star::lang::EventObject const & rSource) + throw (com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + elementInserted(com::sun::star::container::ContainerEvent const & rEvent) + throw (com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + elementRemoved(com::sun::star::container::ContainerEvent const & rEvent) + throw (com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL + elementReplaced(com::sun::star::container::ContainerEvent const & rEvent) + throw (com::sun::star::uno::RuntimeException); + +private: + JavaVirtualMachine(JavaVirtualMachine &); // not implemented + void operator =(JavaVirtualMachine); // not implemented + + virtual ~JavaVirtualMachine(); + + virtual void SAL_CALL disposing(); + + JavaVM * createJavaVM(JVM const & jvm, JNIEnv ** pMainThreadEnv); + // throws com::sun::star::uno::RuntimeException + + void registerConfigChangesListener(); + + void setINetSettingsInVM(bool set_reset); + + void setUpUnoVirtualMachine(JNIEnv * environment); + + void handleJniException(JNIEnv * environment); + + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + m_xContext; + + // the following are controlled by the 'this' mutex: + bool m_bDisposed; + rtl::Reference< jvmaccess::VirtualMachine > m_xVirtualMachine; + rtl::Reference< jvmaccess::UnoVirtualMachine > m_xUnoVirtualMachine; + JavaVM * m_pJavaVm; + // stored as an instance member for backwards compatibility in getJavaVM + bool m_bDontCreateJvm; + // If the first creation of Java failed and this flag is set then the + // next call to getJavaVM throws a RuntimException. This is useful when + // the second attempt to create Java might cause a crash. + com::sun::star::uno::Reference< com::sun::star::container::XContainer > + m_xInetConfiguration; + com::sun::star::uno::Reference< com::sun::star::container::XContainer > + m_xJavaConfiguration; // for Java settings + + osl::ThreadData m_aAttachGuards; +}; + +} + +#endif // INCLUDED_STOC_JAVAVM_JAVAVM_HXX diff --git a/stoc/source/javavm/jen.xml b/stoc/source/javavm/jen.xml new file mode 100644 index 000000000000..29ceb09db110 --- /dev/null +++ b/stoc/source/javavm/jen.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + <module-name> javavm.uno </module-name> + <component-description> + <author> Kay Ramme </author> + <name> com.sun.star.comp.stoc.JavaVirtualMachine </name> + <description> +The Java VM service manages the creation of java vms. +It takes a look at the UNO runtime and tries to find a java environment. +If an java environment already exists, no new vm is created, instead +the existing vm given back. +</description> + <loader-name> com.sun.star.loader.SharedLibrary </loader-name> + <language> c++ </language> + <status value="final"/> + <supported-service> com.sun.star.java.JavaVirtualMachine </supported-service> + <service-dependency> ... </service-dependency> + <type>com.sun.star.beans.NamedValue</type> + <type>com.sun.star.java.XJavaThreadRegister_11</type> + <type>com.sun.star.uri/ExternalUriReferenceTranslator</type> + <type>com.sun.star.util.XMacroExpander</type> + <type> com.sun.star.java.XJavaVM </type> + <type> com.sun.star.java.XJavaVM </type> + <type> com.sun.star.container.XNameAccess </type> + <type> com.sun.star.container.XContainer </type> + <type> com.sun.star.container.XContainerListener </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.WrappedTargetRuntimeException </type> + <type> com.sun.star.lang.DisposedException </type> + <type> com.sun.star.lang.IllegalArgumentException </type> + <type> com.sun.star.lang.XInitialization </type> + <type> com.sun.star.registry.XSimpleRegistry </type> + <type> com.sun.star.lang.XSingleComponentFactory </type> + <type> com.sun.star.uno.XComponentContext </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.uno.TypeClass </type> + <type> com.sun.star.uno.XCurrentContext </type> + <type> com.sun.star.beans.PropertyValue </type> + <type> com.sun.star.task.XInteractionHandler </type> + <type> com.sun.star.task.XInteractionRequest </type> + <type> com.sun.star.task.XInteractionContinuation </type> + <type> com.sun.star.task.XInteractionAbort </type> + <type> com.sun.star.task.XInteractionRetry </type> + <type> com.sun.star.java.JavaInitializationException </type> + <type> com.sun.star.java.JavaDisabledException </type> + <type> com.sun.star.java.JavaNotFoundException </type> + <type> com.sun.star.java.InvalidJavaSettingsException </type> + <type> com.sun.star.java.RestartRequiredException </type> + <type> com.sun.star.java.JavaVMCreationFailureException </type> + <type> com.sun.star.container.XNameAccess </type> + </component-description> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> tools </project-build-dependency> + <project-build-dependency> sal </project-build-dependency> + <project-build-dependency> jvmaccess </project-build-dependency> + <project-build-dependency> salhelper </project-build-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> tl(COM) </runtime-module-dependency> + <runtime-module-dependency> sal3 </runtime-module-dependency> + <runtime-module-dependency> jvmaccess3$(COM) </runtime-module-dependency> + <runtime-module-dependency> salhelper3$(COM) </runtime-module-dependency> +</module-description> diff --git a/stoc/source/javavm/jvmargs.cxx b/stoc/source/javavm/jvmargs.cxx new file mode 100644 index 000000000000..8563b46a41f9 --- /dev/null +++ b/stoc/source/javavm/jvmargs.cxx @@ -0,0 +1,66 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include "jvmargs.hxx" +#include <rtl/ustring.hxx> + + +#define OUSTR(x) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( x )) + +using namespace rtl; + +namespace stoc_javavm { + +JVM::JVM() throw()//: _enabled(sal_False) +{ +} + +void JVM::pushProp(const OUString & property) +{ + sal_Int32 index = property.indexOf((sal_Unicode)'='); + if(index > 0) + { + OUString left = property.copy(0, index).trim(); + OUString right(property.copy(index + 1).trim()); + _props.push_back(property); + } + else + { // no '=', could be -X + _props.push_back(property); + } +} + + +const ::std::vector< ::rtl::OUString > & JVM::getProperties() const +{ + return _props; +} + +} diff --git a/stoc/source/javavm/jvmargs.hxx b/stoc/source/javavm/jvmargs.hxx new file mode 100644 index 000000000000..5eae66da9d07 --- /dev/null +++ b/stoc/source/javavm/jvmargs.hxx @@ -0,0 +1,58 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + + +#ifndef __JVM_HXX +#define __JVM_HXX + + +#include <vector> +#include <rtl/ustring.hxx> + +#include "jni.h" + + +extern "C" { + typedef jint JNICALL JNI_InitArgs_Type(void *); + typedef jint JNICALL JNI_CreateVM_Type(JavaVM **, JNIEnv **, void *); + +} + +namespace stoc_javavm { + + class JVM { + ::std::vector<rtl::OUString> _props; + + public: + JVM() throw(); + + void pushProp(const ::rtl::OUString & uString); + const ::std::vector< ::rtl::OUString> & getProperties() const; + }; +} + +#endif diff --git a/stoc/source/javavm/makefile.mk b/stoc/source/javavm/makefile.mk new file mode 100644 index 000000000000..bcd36e69681e --- /dev/null +++ b/stoc/source/javavm/makefile.mk @@ -0,0 +1,94 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME=stoc +TARGET = javavm.uno +ENABLE_EXCEPTIONS=TRUE +COMP1TYPELIST = jen + +.IF "$(SOLAR_JAVA)" == "TRUE" +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +DLLPRE = + +# --- Files -------------------------------------------------------- + +# Kollision zwischen bool.h aus Java und bool.h aus der STL. +# Das Problem tritt fuer alle Plattformen auf, aber anscheinend stolpert nur der +# GCC darueber +.IF "$(COM)" == "GCC" +CDEFS += -D__SGI_STL_BOOL_H +.ENDIF + +.INCLUDE : ..$/cppumaker.mk + +SLOFILES= \ + $(SLO)$/javavm.obj \ + $(SLO)$/jvmargs.obj \ + $(SLO)$/interact.obj + +SHL1TARGET= $(TARGET) +SHL1VERSIONMAP = $(SOLARENV)/src/component.map +SHL1STDLIBS= \ + $(CPPUHELPERLIB) \ + $(CPPULIB) \ + $(SALLIB) \ + $(JVMACCESSLIB) \ + $(SALHELPERLIB) \ + $(JVMFWKLIB) + +.IF "$(GUI)"=="WNT" +SHL1STDLIBS += $(ADVAPI32LIB) +.ENDIF + +SHL1DEPN= +SHL1IMPLIB= i$(TARGET) +SHL1LIBS= $(SLB)$/$(TARGET).lib +SHL1DEF= $(MISC)$/$(SHL1TARGET).def +SHL1RPATH= URELIB + +DEF1NAME= $(SHL1TARGET) + +.ELSE # SOLAR_JAVA +all: + @echo Nothing to do: SOLAR_JAVA not set +.ENDIF + +# --- Targets ------------------------------------------------------ + + +.INCLUDE : target.mk + +ALLTAR : $(MISC)/javavm.component + +$(MISC)/javavm.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + javavm.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_URE_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt javavm.component diff --git a/stoc/source/loader/dllcomponentloader.cxx b/stoc/source/loader/dllcomponentloader.cxx new file mode 100644 index 000000000000..d50f209718ed --- /dev/null +++ b/stoc/source/loader/dllcomponentloader.cxx @@ -0,0 +1,261 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include <stdlib.h> +#include <osl/file.h> +#include <vector> +#include <osl/mutex.hxx> +#include <osl/diagnose.h> +#include <osl/module.h> +#include <rtl/ustring.hxx> +#include <uno/environment.h> +#include <uno/mapping.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/weak.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/shlib.hxx> +#include <cppuhelper/implbase3.hxx> +#ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX__ +#include <cppuhelper/implementationentry.hxx> +#endif +#include <cppuhelper/bootstrap.hxx> + +#include <com/sun/star/loader/XImplementationLoader.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> + +#define SERVICENAME "com.sun.star.loader.SharedLibrary" +#define IMPLNAME "com.sun.star.comp.stoc.DLLComponentLoader" + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + + +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::loader; +using namespace com::sun::star::lang; +using namespace com::sun::star::registry; +using namespace cppu; +using namespace rtl; +using namespace osl; + +extern rtl_StandardModuleCount g_moduleCount; + +namespace stoc_bootstrap +{ +Sequence< OUString > loader_getSupportedServiceNames() +{ + static Sequence < OUString > *pNames = 0; + if( ! pNames ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( !pNames ) + { + static Sequence< OUString > seqNames(1); + seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME)); + pNames = &seqNames; + } + } + return *pNames; +} + +OUString loader_getImplementationName() +{ + static OUString *pImplName = 0; + if( ! pImplName ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( ! pImplName ) + { + static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) ); + pImplName = &implName; + } + } + return *pImplName; +} +} + +namespace stoc_loader +{ +//************************************************************************* +// DllComponentLoader +//************************************************************************* +class DllComponentLoader + : public WeakImplHelper3< XImplementationLoader, + XInitialization, + XServiceInfo > +{ +public: + DllComponentLoader( const Reference<XComponentContext> & xCtx ); + ~DllComponentLoader(); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) throw(::com::sun::star::uno::RuntimeException); + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XImplementationLoader + virtual Reference<XInterface> SAL_CALL activate( const OUString& implementationName, const OUString& implementationLoaderUrl, const OUString& locationUrl, const Reference<XRegistryKey>& xKey ) throw(CannotActivateFactoryException, RuntimeException); + virtual sal_Bool SAL_CALL writeRegistryInfo( const Reference<XRegistryKey>& xKey, const OUString& implementationLoaderUrl, const OUString& locationUrl ) throw(CannotRegisterImplementationException, RuntimeException); + +private: + OUString expand_url( OUString const & url ) + SAL_THROW( (RuntimeException) ); + + Reference<XMultiServiceFactory> m_xSMgr; +}; + +//************************************************************************* +DllComponentLoader::DllComponentLoader( const Reference<XComponentContext> & xCtx ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + m_xSMgr.set( xCtx->getServiceManager(), UNO_QUERY ); +} + +//************************************************************************* +DllComponentLoader::~DllComponentLoader() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +//************************************************************************* +OUString SAL_CALL DllComponentLoader::getImplementationName( ) + throw(::com::sun::star::uno::RuntimeException) +{ + return stoc_bootstrap::loader_getImplementationName(); +} + +//************************************************************************* +sal_Bool SAL_CALL DllComponentLoader::supportsService( const OUString& ServiceName ) + throw(::com::sun::star::uno::RuntimeException) +{ + Sequence< OUString > aSNL = getSupportedServiceNames(); + const OUString * pArray = aSNL.getArray(); + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return sal_True; + return sal_False; +} + +//************************************************************************* +Sequence<OUString> SAL_CALL DllComponentLoader::getSupportedServiceNames( ) + throw(::com::sun::star::uno::RuntimeException) +{ + return stoc_bootstrap::loader_getSupportedServiceNames(); +} + +//************************************************************************* +void DllComponentLoader::initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& ) + throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + OSL_ENSURE( 0, "dllcomponentloader::initialize should not be called !" ); +// if( aArgs.getLength() != 1 ) +// { +// throw IllegalArgumentException(); +// } + +// Reference< XMultiServiceFactory > rServiceManager; + +// if( aArgs.getConstArray()[0].getValueType().getTypeClass() == TypeClass_INTERFACE ) +// { +// aArgs.getConstArray()[0] >>= rServiceManager; +// } + +// if( !rServiceManager.is() ) +// { +// throw IllegalArgumentException(); +// } + +// m_xSMgr = rServiceManager; +} + +//================================================================================================== +OUString DllComponentLoader::expand_url( OUString const & url ) + SAL_THROW( (RuntimeException) ) +{ + try + { + return cppu::bootstrap_expandUri( url ); + } + catch ( IllegalArgumentException & e ) + { + throw RuntimeException( e.Message, e.Context ); + } +} + +//************************************************************************* +Reference<XInterface> SAL_CALL DllComponentLoader::activate( + const OUString & rImplName, const OUString &, const OUString & rLibName, + const Reference< XRegistryKey > & xKey ) + + throw(CannotActivateFactoryException, RuntimeException) +{ + return loadSharedLibComponentFactory( + expand_url( rLibName ), OUString(), rImplName, m_xSMgr, xKey ); +} + + +//************************************************************************* +sal_Bool SAL_CALL DllComponentLoader::writeRegistryInfo( + const Reference< XRegistryKey > & xKey, const OUString &, const OUString & rLibName ) + + throw(CannotRegisterImplementationException, RuntimeException) +{ + writeSharedLibComponentInfo( + expand_url( rLibName ), OUString(), m_xSMgr, xKey ); + return sal_True; +} +} + +namespace stoc_bootstrap +{ +//************************************************************************* +Reference<XInterface> SAL_CALL DllComponentLoader_CreateInstance( const Reference<XComponentContext> & xCtx ) throw(Exception) +{ + Reference<XInterface> xRet; + + XImplementationLoader *pXLoader = (XImplementationLoader *)new stoc_loader::DllComponentLoader(xCtx); + + if (pXLoader) + { + xRet = Reference<XInterface>::query(pXLoader); + } + + return xRet; +} + +} + diff --git a/stoc/source/loader/makefile.mk b/stoc/source/loader/makefile.mk new file mode 100644 index 000000000000..24a39597a8cd --- /dev/null +++ b/stoc/source/loader/makefile.mk @@ -0,0 +1,47 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME= stoc +TARGET = shlibloader +ENABLE_EXCEPTIONS=TRUE +BOOTSTRAP_SERVICE=TRUE +UNOUCROUT= $(OUT)$/inc$/bootstrap + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# ------------------------------------------------------------------ + +SLOFILES= \ + $(SLO)$/dllcomponentloader.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/stoc/source/module-description.dtd b/stoc/source/module-description.dtd new file mode 100644 index 000000000000..279f721de1da --- /dev/null +++ b/stoc/source/module-description.dtd @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + Copyright 2000, 2010 Oracle and/or its affiliates. + + OpenOffice.org - a multi-platform office productivity suite + + This file is part of OpenOffice.org. + + OpenOffice.org is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + OpenOffice.org is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details + (a copy is included in the LICENSE file that accompanied this code). + + You should have received a copy of the GNU Lesser General Public License + version 3 along with OpenOffice.org. If not, see + <http://www.openoffice.org/license.html> + for a copy of the LGPLv3 License. + +--> + +<!ENTITY % component-description-optional "reference-docu|service-dependency|type"> +<!ENTITY % module-description-optional "project-build-dependency|runtime-module-dependency|(%component-description-optional;)"> +<!ELEMENT module-description (module-name, component-description*,(%module-description-optional;)* )> +<!ELEMENT component-description (author,name,description,loader-name,language,status, supported-service+, (%component-description-optional;)* )> + +<!ELEMENT author (#PCDATA)> +<!ELEMENT name (#PCDATA)> +<!ELEMENT description (#PCDATA)> +<!ELEMENT reference-docu EMPTY > +<!ATTLIST reference-docu + xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink/Namespace" + xlink:type (simple) #FIXED "simple" + xlink:href CDATA #REQUIRED + xlink:role NMTOKEN #IMPLIED + xlink:title CDATA #IMPLIED > + +<!ELEMENT module-name (#PCDATA)> +<!ELEMENT loader-name (#PCDATA)> +<!ELEMENT supported-service (#PCDATA)> +<!ELEMENT service-dependency (#PCDATA)> +<!ELEMENT project-build-dependency (#PCDATA)> +<!ELEMENT runtime-module-dependency (#PCDATA)> +<!ELEMENT language (#PCDATA)> +<!ELEMENT status EMPTY > +<!ATTLIST status value (under_construction | alpha | beta | final) #REQUIRED> +<!ELEMENT type (#PCDATA)> diff --git a/stoc/source/namingservice/makefile.mk b/stoc/source/namingservice/makefile.mk new file mode 100644 index 000000000000..cc98cdfc3571 --- /dev/null +++ b/stoc/source/namingservice/makefile.mk @@ -0,0 +1,73 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME= stoc +TARGET = namingservice.uno +ENABLE_EXCEPTIONS=TRUE +COMP1TYPELIST = namingservice + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +DLLPRE = + +# ------------------------------------------------------------------ + +.INCLUDE : ..$/cppumaker.mk + +SLOFILES= \ + $(SLO)$/namingservice.obj + +SHL1TARGET= $(TARGET) + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) + +SHL1VERSIONMAP = $(SOLARENV)/src/unloadablecomponent.map + +SHL1DEPN= +SHL1IMPLIB= i$(TARGET) +SHL1LIBS= $(SLB)$/$(TARGET).lib +SHL1DEF= $(MISC)$/$(SHL1TARGET).def +SHL1RPATH= URELIB + +DEF1NAME= $(SHL1TARGET) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +ALLTAR : $(MISC)/namingservice.component + +$(MISC)/namingservice.component .ERRREMOVE : \ + $(SOLARENV)/bin/createcomponent.xslt namingservice.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_URE_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt namingservice.component diff --git a/stoc/source/namingservice/namingservice.component b/stoc/source/namingservice/namingservice.component new file mode 100644 index 000000000000..8450cdee6d7e --- /dev/null +++ b/stoc/source/namingservice/namingservice.component @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.stoc.NamingService"> + <service name="com.sun.star.uno.NamingService"/> + </implementation> +</component> diff --git a/stoc/source/namingservice/namingservice.cxx b/stoc/source/namingservice/namingservice.cxx new file mode 100644 index 000000000000..a2ea1d361202 --- /dev/null +++ b/stoc/source/namingservice/namingservice.cxx @@ -0,0 +1,246 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include <hash_map> +#include <osl/mutex.hxx> +#include <osl/diagnose.h> +#include <uno/dispatcher.h> +#include <uno/mapping.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/weak.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/component.hxx> +#include <cppuhelper/implbase2.hxx> +#ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_ +#include <cppuhelper/implementationentry.hxx> +#endif + +#include <com/sun/star/uno/XNamingService.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> + +using namespace cppu; +using namespace rtl; +using namespace osl; +using namespace std; + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::registry; + +#define SERVICENAME "com.sun.star.uno.NamingService" +#define IMPLNAME "com.sun.star.comp.stoc.NamingService" + +namespace stoc_namingservice +{ +static rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT; + +static Sequence< OUString > ns_getSupportedServiceNames() +{ + static Sequence < OUString > *pNames = 0; + if( ! pNames ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( !pNames ) + { + static Sequence< OUString > seqNames(1); + seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME)); + pNames = &seqNames; + } + } + return *pNames; +} + +static OUString ns_getImplementationName() +{ + static OUString *pImplName = 0; + if( ! pImplName ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( ! pImplName ) + { + static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) ); + pImplName = &implName; + } + } + return *pImplName; +} + +struct equalOWString_Impl +{ + sal_Bool operator()(const OUString & s1, const OUString & s2) const + { return s1 == s2; } +}; + +struct hashOWString_Impl +{ + size_t operator()(const OUString & rName) const + { return rName.hashCode(); } +}; + +typedef hash_map +< + OUString, + Reference<XInterface >, + hashOWString_Impl, + equalOWString_Impl +> HashMap_OWString_Interface; + +//================================================================================================== +class NamingService_Impl + : public WeakImplHelper2 < XServiceInfo, XNamingService > +{ + Mutex aMutex; + HashMap_OWString_Interface aMap; +public: + NamingService_Impl(); + ~NamingService_Impl(); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() + throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) + throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() + throw(::com::sun::star::uno::RuntimeException); + static Sequence< OUString > SAL_CALL getSupportedServiceNames_Static() + { + OUString aStr( OUString::createFromAscii( SERVICENAME ) ); + return Sequence< OUString >( &aStr, 1 ); + } + + virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getRegisteredObject( const ::rtl::OUString& Name ) throw(Exception, RuntimeException); + virtual void SAL_CALL registerObject( const ::rtl::OUString& Name, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& Object ) throw(Exception, RuntimeException); + virtual void SAL_CALL revokeObject( const ::rtl::OUString& Name ) throw(Exception, RuntimeException); +}; + +//================================================================================================== +static Reference<XInterface> SAL_CALL NamingService_Impl_create( const Reference<XComponentContext> & ) +{ + return *new NamingService_Impl(); +} + +//================================================================================================== +NamingService_Impl::NamingService_Impl() +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); +} + +//================================================================================================== +NamingService_Impl::~NamingService_Impl() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +// XServiceInfo +OUString NamingService_Impl::getImplementationName() + throw(::com::sun::star::uno::RuntimeException) +{ + return ns_getImplementationName(); +} + +// XServiceInfo +sal_Bool NamingService_Impl::supportsService( const OUString & rServiceName ) + throw(::com::sun::star::uno::RuntimeException) +{ + const Sequence< OUString > & rSNL = getSupportedServiceNames(); + const OUString * pArray = rSNL.getConstArray(); + for ( sal_Int32 nPos = rSNL.getLength(); nPos--; ) + { + if (pArray[nPos] == rServiceName) + return sal_True; + } + return sal_False; +} + +// XServiceInfo +Sequence< OUString > NamingService_Impl::getSupportedServiceNames() + throw(::com::sun::star::uno::RuntimeException) +{ + return ns_getSupportedServiceNames(); +} + +// XServiceInfo +Reference< XInterface > NamingService_Impl::getRegisteredObject( const OUString& Name ) throw(Exception, RuntimeException) +{ + Guard< Mutex > aGuard( aMutex ); + Reference< XInterface > xRet; + HashMap_OWString_Interface::iterator aIt = aMap.find( Name ); + if( aIt != aMap.end() ) + xRet = (*aIt).second; + return xRet; +} + +// XServiceInfo +void NamingService_Impl::registerObject( const OUString& Name, const Reference< XInterface >& Object ) throw(Exception, RuntimeException) +{ + Guard< Mutex > aGuard( aMutex ); + aMap[ Name ] = Object; +} + +// XServiceInfo +void NamingService_Impl::revokeObject( const OUString& Name ) throw(Exception, RuntimeException) +{ + Guard< Mutex > aGuard( aMutex ); + aMap.erase( Name ); +} + +} + +using namespace stoc_namingservice; +static struct ImplementationEntry g_entries[] = +{ + { + NamingService_Impl_create, ns_getImplementationName, + ns_getSupportedServiceNames, createSingleComponentFactory, + &g_moduleCount.modCnt , 0 + }, + { 0, 0, 0, 0, 0, 0 } +}; + +extern "C" +{ +sal_Bool SAL_CALL component_canUnload( TimeValue *pTime ) +{ + return g_moduleCount.canUnload( &g_moduleCount , pTime ); +} + +//================================================================================================== +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} +//================================================================================================== +void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) +{ + return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries ); +} +} diff --git a/stoc/source/namingservice/namingservice.xml b/stoc/source/namingservice/namingservice.xml new file mode 100644 index 000000000000..2b9d9365ea62 --- /dev/null +++ b/stoc/source/namingservice/namingservice.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + <module-name> namingservice.uno </module-name> + <component-description> + <author> Juergen Schmidt </author> + <name> com.sun.star.comp.stoc.NamingService </name> + <description> +The naming service allows the registration and retrieval of objects. +</description> + <loader-name> com.sun.star.loader.SharedLibrary </loader-name> + <language> c++ </language> + <status value="final"/> + <supported-service> com.sun.star.uno.NamingService </supported-service> + <type>com.sun.star.lang.DisposedException</type> + <type> com.sun.star.lang.XComponent </type> + <type> com.sun.star.lang.IllegalArgumentException </type> + <type> com.sun.star.lang.XInitialization </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleComponentFactory </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.uno.XComponentContext </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.uno.TypeClass </type> + <type> com.sun.star.uno.XNamingService </type> + </component-description> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> sal </project-build-dependency> + <runtime-module-dependency> cppuhelper3$(COM) </runtime-module-dependency> + <runtime-module-dependency> cppu3 </runtime-module-dependency> + <runtime-module-dependency> sal3 </runtime-module-dependency> +</module-description> diff --git a/stoc/source/proxy_factory/makefile.mk b/stoc/source/proxy_factory/makefile.mk new file mode 100644 index 000000000000..23146e678f5a --- /dev/null +++ b/stoc/source/proxy_factory/makefile.mk @@ -0,0 +1,73 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=stoc +TARGET = proxyfac.uno +ENABLE_EXCEPTIONS=TRUE +COMP1TYPELIST = proxyfac + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +DLLPRE = + +# ------------------------------------------------------------------ + +.INCLUDE : ..$/cppumaker.mk + +SLOFILES= \ + $(SLO)$/proxyfac.obj + +SHL1TARGET=$(TARGET) +SHL1VERSIONMAP = $(SOLARENV)/src/unloadablecomponent.map + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) + +SHL1DEPN= +SHL1IMPLIB=i$(TARGET) +SHL1LIBS=$(SLB)$/$(TARGET).lib +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +SHL1RPATH=URELIB + +DEF1NAME=$(SHL1TARGET) + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +ALLTAR : $(MISC)/proxyfac.component + +$(MISC)/proxyfac.component .ERRREMOVE : $(SOLARENV)/bin/createcomponent.xslt \ + proxyfac.component + $(XSLTPROC) --nonet --stringparam uri \ + '$(COMPONENTPREFIX_URE_NATIVE)$(SHL1TARGETN:f)' -o $@ \ + $(SOLARENV)/bin/createcomponent.xslt proxyfac.component diff --git a/stoc/source/proxy_factory/proxyfac.component b/stoc/source/proxy_factory/proxyfac.component new file mode 100644 index 000000000000..bfe2c9c4268a --- /dev/null +++ b/stoc/source/proxy_factory/proxyfac.component @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.reflection.ProxyFactory"> + <service name="com.sun.star.reflection.ProxyFactory"/> + </implementation> +</component> diff --git a/stoc/source/proxy_factory/proxyfac.cxx b/stoc/source/proxy_factory/proxyfac.cxx new file mode 100644 index 000000000000..644f8ecb624c --- /dev/null +++ b/stoc/source/proxy_factory/proxyfac.cxx @@ -0,0 +1,537 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include "osl/diagnose.h" +#include "osl/interlck.h" +#include "osl/doublecheckedlocking.h" +#include "osl/mutex.hxx" +#include "rtl/ref.hxx" +#include "uno/dispatcher.hxx" +#include "uno/data.h" +#include "uno/mapping.hxx" +#include "uno/environment.hxx" +#include "typelib/typedescription.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "cppuhelper/implbase2.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "cppuhelper/factory.hxx" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/registry/XRegistryKey.hpp" +#include "com/sun/star/reflection/XProxyFactory.hpp" +#include "com/sun/star/uno/RuntimeException.hpp" + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) +#define SERVICE_NAME "com.sun.star.reflection.ProxyFactory" +#define IMPL_NAME "com.sun.star.comp.reflection.ProxyFactory" + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; + + +namespace +{ + +static rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT; + +static OUString proxyfac_getImplementationName() +{ + return OUSTR(IMPL_NAME); +} + +static Sequence< OUString > proxyfac_getSupportedServiceNames() +{ + OUString str_name = OUSTR(SERVICE_NAME); + return Sequence< OUString >( &str_name, 1 ); +} + +//============================================================================== +struct FactoryImpl : public ::cppu::WeakImplHelper2< lang::XServiceInfo, + reflection::XProxyFactory > +{ + Environment m_uno_env; + Environment m_cpp_env; + Mapping m_uno2cpp; + Mapping m_cpp2uno; + + UnoInterfaceReference binuno_queryInterface( + UnoInterfaceReference const & unoI, + typelib_InterfaceTypeDescription * pTypeDescr ); + + FactoryImpl(); + virtual ~FactoryImpl(); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() + throw (RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) + throw (RuntimeException); + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() + throw (RuntimeException); + + // XProxyFactory + virtual Reference< XAggregation > SAL_CALL createProxy( + Reference< XInterface > const & xTarget ) + throw (RuntimeException); +}; + +//______________________________________________________________________________ +UnoInterfaceReference FactoryImpl::binuno_queryInterface( + UnoInterfaceReference const & unoI, + typelib_InterfaceTypeDescription * pTypeDescr ) +{ + // init queryInterface() td + static typelib_TypeDescription * s_pQITD = 0; + if (s_pQITD == 0) + { + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if (s_pQITD == 0) + { + typelib_TypeDescription * pTXInterfaceDescr = 0; + TYPELIB_DANGER_GET( + &pTXInterfaceDescr, + ::getCppuType( reinterpret_cast< Reference< XInterface > + const * >(0) ).getTypeLibType() ); + typelib_TypeDescription * pQITD = 0; + typelib_typedescriptionreference_getDescription( + &pQITD, reinterpret_cast< typelib_InterfaceTypeDescription * >( + pTXInterfaceDescr )->ppAllMembers[ 0 ] ); + TYPELIB_DANGER_RELEASE( pTXInterfaceDescr ); + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + s_pQITD = pQITD; + } + } + else + { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + + void * args[ 1 ]; + args[ 0 ] = &reinterpret_cast< typelib_TypeDescription * >( + pTypeDescr )->pWeakRef; + uno_Any ret_val, exc_space; + uno_Any * exc = &exc_space; + + unoI.dispatch( s_pQITD, &ret_val, args, &exc ); + + if (exc == 0) + { + UnoInterfaceReference ret; + if (ret_val.pType->eTypeClass == typelib_TypeClass_INTERFACE) + { + ret.set( *reinterpret_cast< uno_Interface ** >(ret_val.pData), + SAL_NO_ACQUIRE ); + typelib_typedescriptionreference_release( ret_val.pType ); + } + else + { + uno_any_destruct( &ret_val, 0 ); + } + return ret; + } + else + { + // exception occured: + OSL_ENSURE( + typelib_typedescriptionreference_isAssignableFrom( + ::getCppuType( reinterpret_cast< + RuntimeException const * >(0) ).getTypeLibType(), + exc->pType ), + "### RuntimeException expected!" ); + Any cpp_exc; + uno_type_copyAndConvertData( + &cpp_exc, exc, ::getCppuType( &cpp_exc ).getTypeLibType(), + m_uno2cpp.get() ); + uno_any_destruct( exc, 0 ); + ::cppu::throwException( cpp_exc ); + OSL_ASSERT( 0 ); // way of no return + return UnoInterfaceReference(); // for dummy + } +} + +//============================================================================== +struct ProxyRoot : public ::cppu::OWeakAggObject +{ + // XAggregation + virtual Any SAL_CALL queryAggregation( Type const & rType ) + throw (RuntimeException); + + virtual ~ProxyRoot(); + inline ProxyRoot( ::rtl::Reference< FactoryImpl > const & factory, + Reference< XInterface > const & xTarget ); + + ::rtl::Reference< FactoryImpl > m_factory; + +private: + UnoInterfaceReference m_target; +}; + +//============================================================================== +struct binuno_Proxy : public uno_Interface +{ + oslInterlockedCount m_nRefCount; + ::rtl::Reference< ProxyRoot > m_root; + UnoInterfaceReference m_target; + OUString m_oid; + TypeDescription m_typeDescr; + + inline binuno_Proxy( + ::rtl::Reference< ProxyRoot > const & root, + UnoInterfaceReference const & target, + OUString const & oid, TypeDescription const & typeDescr ); +}; + +extern "C" +{ + +//------------------------------------------------------------------------------ +static void SAL_CALL binuno_proxy_free( + uno_ExtEnvironment * pEnv, void * pProxy ) +{ + (void) pEnv; // avoid warning about unused parameter + binuno_Proxy * proxy = static_cast< binuno_Proxy * >( + reinterpret_cast< uno_Interface * >( pProxy ) ); + OSL_ASSERT( proxy->m_root->m_factory->m_uno_env.get()->pExtEnv == pEnv ); + delete proxy; +} + +//------------------------------------------------------------------------------ +static void SAL_CALL binuno_proxy_acquire( uno_Interface * pUnoI ) +{ + binuno_Proxy * that = static_cast< binuno_Proxy * >( pUnoI ); + if (osl_incrementInterlockedCount( &that->m_nRefCount ) == 1) + { + // rebirth of zombie + uno_ExtEnvironment * uno_env = + that->m_root->m_factory->m_uno_env.get()->pExtEnv; + OSL_ASSERT( uno_env != 0 ); + (*uno_env->registerProxyInterface)( + uno_env, reinterpret_cast< void ** >( &pUnoI ), binuno_proxy_free, + that->m_oid.pData, + reinterpret_cast< typelib_InterfaceTypeDescription * >( + that->m_typeDescr.get() ) ); + OSL_ASSERT( that == static_cast< binuno_Proxy * >( pUnoI ) ); + } +} + +//------------------------------------------------------------------------------ +static void SAL_CALL binuno_proxy_release( uno_Interface * pUnoI ) +{ + binuno_Proxy * that = static_cast< binuno_Proxy * >( pUnoI ); + if (osl_decrementInterlockedCount( &that->m_nRefCount ) == 0) + { + uno_ExtEnvironment * uno_env = + that->m_root->m_factory->m_uno_env.get()->pExtEnv; + OSL_ASSERT( uno_env != 0 ); + (*uno_env->revokeInterface)( uno_env, pUnoI ); + } +} + +//------------------------------------------------------------------------------ +static void SAL_CALL binuno_proxy_dispatch( + uno_Interface * pUnoI, const typelib_TypeDescription * pMemberType, + void * pReturn, void * pArgs [], uno_Any ** ppException ) +{ + binuno_Proxy * that = static_cast< binuno_Proxy * >( pUnoI ); + switch (reinterpret_cast< typelib_InterfaceMemberTypeDescription const * >( + pMemberType )->nPosition) + { + case 0: // queryInterface() + { + try + { + Type const & rType = + *reinterpret_cast< Type const * >( pArgs[ 0 ] ); + Any ret( that->m_root->queryInterface( rType ) ); + uno_type_copyAndConvertData( + pReturn, &ret, ::getCppuType( &ret ).getTypeLibType(), + that->m_root->m_factory->m_cpp2uno.get() ); + *ppException = 0; // no exc + } + catch (RuntimeException &) + { + Any exc( ::cppu::getCaughtException() ); + uno_type_any_constructAndConvert( + *ppException, const_cast< void * >(exc.getValue()), + exc.getValueTypeRef(), + that->m_root->m_factory->m_cpp2uno.get() ); + } + break; + } + case 1: // acquire() + binuno_proxy_acquire( pUnoI ); + *ppException = 0; // no exc + break; + case 2: // release() + binuno_proxy_release( pUnoI ); + *ppException = 0; // no exc + break; + default: + that->m_target.dispatch( pMemberType, pReturn, pArgs, ppException ); + break; + } +} + +} + +//______________________________________________________________________________ +inline binuno_Proxy::binuno_Proxy( + ::rtl::Reference< ProxyRoot > const & root, + UnoInterfaceReference const & target, + OUString const & oid, TypeDescription const & typeDescr ) + : m_nRefCount( 1 ), + m_root( root ), + m_target( target ), + m_oid( oid ), + m_typeDescr( typeDescr ) +{ + uno_Interface::acquire = binuno_proxy_acquire; + uno_Interface::release = binuno_proxy_release; + uno_Interface::pDispatcher = binuno_proxy_dispatch; +} + +//______________________________________________________________________________ +ProxyRoot::~ProxyRoot() +{ +} + +//______________________________________________________________________________ +inline ProxyRoot::ProxyRoot( + ::rtl::Reference< FactoryImpl > const & factory, + Reference< XInterface > const & xTarget ) + : m_factory( factory ) +{ + m_factory->m_cpp2uno.mapInterface( + reinterpret_cast< void ** >( &m_target.m_pUnoI ), xTarget.get(), + ::getCppuType( &xTarget ) ); + OSL_ENSURE( m_target.is(), "### mapping interface failed!" ); +} + +//______________________________________________________________________________ +Any ProxyRoot::queryAggregation( Type const & rType ) + throw (RuntimeException) +{ + Any ret( OWeakAggObject::queryAggregation( rType ) ); + if (! ret.hasValue()) + { + typelib_TypeDescription * pTypeDescr = 0; + TYPELIB_DANGER_GET( &pTypeDescr, rType.getTypeLibType() ); + try + { + Reference< XInterface > xProxy; + uno_ExtEnvironment * cpp_env = m_factory->m_cpp_env.get()->pExtEnv; + OSL_ASSERT( cpp_env != 0 ); + + // mind a new delegator, calculate current root: + Reference< XInterface > xRoot( + static_cast< OWeakObject * >(this), UNO_QUERY_THROW ); + OUString oid; + (*cpp_env->getObjectIdentifier)( cpp_env, &oid.pData, xRoot.get() ); + OSL_ASSERT( oid.getLength() > 0 ); + + (*cpp_env->getRegisteredInterface)( + cpp_env, reinterpret_cast< void ** >( &xProxy ), + oid.pData, reinterpret_cast< + typelib_InterfaceTypeDescription * >(pTypeDescr) ); + if (! xProxy.is()) + { + // perform query on target: + UnoInterfaceReference proxy_target( + m_factory->binuno_queryInterface( + m_target, reinterpret_cast< + typelib_InterfaceTypeDescription * >(pTypeDescr) ) ); + if (proxy_target.is()) + { + // ensure root's object entries: + UnoInterfaceReference root; + m_factory->m_cpp2uno.mapInterface( + reinterpret_cast< void ** >( &root.m_pUnoI ), + xRoot.get(), ::getCppuType( &xRoot ) ); + + UnoInterfaceReference proxy( + // ref count initially 1: + new binuno_Proxy( this, proxy_target, oid, pTypeDescr ), + SAL_NO_ACQUIRE ); + uno_ExtEnvironment * uno_env = + m_factory->m_uno_env.get()->pExtEnv; + OSL_ASSERT( uno_env != 0 ); + (*uno_env->registerProxyInterface)( + uno_env, reinterpret_cast< void ** >( &proxy.m_pUnoI ), + binuno_proxy_free, oid.pData, + reinterpret_cast< typelib_InterfaceTypeDescription * >( + pTypeDescr ) ); + + m_factory->m_uno2cpp.mapInterface( + reinterpret_cast< void ** >( &xProxy ), + proxy.get(), pTypeDescr ); + } + } + if (xProxy.is()) + ret.setValue( &xProxy, pTypeDescr ); + } + catch (...) // finally + { + TYPELIB_DANGER_RELEASE( pTypeDescr ); + throw; + } + TYPELIB_DANGER_RELEASE( pTypeDescr ); + } + return ret; +} + +//############################################################################## + +//______________________________________________________________________________ +FactoryImpl::FactoryImpl() +{ + OUString uno = OUSTR(UNO_LB_UNO); + OUString cpp = OUSTR(CPPU_CURRENT_LANGUAGE_BINDING_NAME); + + uno_getEnvironment( + reinterpret_cast< uno_Environment ** >( &m_uno_env ), uno.pData, 0 ); + OSL_ENSURE( m_uno_env.is(), "### cannot get binary uno env!" ); + + uno_getEnvironment( + reinterpret_cast< uno_Environment ** >( &m_cpp_env ), cpp.pData, 0 ); + OSL_ENSURE( m_cpp_env.is(), "### cannot get C++ uno env!" ); + + uno_getMapping( + reinterpret_cast< uno_Mapping ** >( &m_uno2cpp ), + m_uno_env.get(), m_cpp_env.get(), 0 ); + OSL_ENSURE( m_uno2cpp.is(), "### cannot get bridge uno <-> C++!" ); + + uno_getMapping( + reinterpret_cast< uno_Mapping ** >( &m_cpp2uno ), + m_cpp_env.get(), m_uno_env.get(), 0 ); + OSL_ENSURE( m_cpp2uno.is(), "### cannot get bridge C++ <-> uno!" ); + + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); +} + +//______________________________________________________________________________ +FactoryImpl::~FactoryImpl() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +// XProxyFactory +//______________________________________________________________________________ +Reference< XAggregation > FactoryImpl::createProxy( + Reference< XInterface > const & xTarget ) + throw (RuntimeException) +{ + return new ProxyRoot( this, xTarget ); +} + +// XServiceInfo +//______________________________________________________________________________ +OUString FactoryImpl::getImplementationName() + throw (RuntimeException) +{ + return proxyfac_getImplementationName();; +} + +//______________________________________________________________________________ +sal_Bool FactoryImpl::supportsService( const OUString & rServiceName ) + throw (RuntimeException) +{ + Sequence< OUString > const & rSNL = getSupportedServiceNames(); + OUString const * pArray = rSNL.getConstArray(); + for ( sal_Int32 nPos = rSNL.getLength(); nPos--; ) + { + if (rServiceName.equals( pArray[ nPos ] )) + return true; + } + return false; +} + +//______________________________________________________________________________ +Sequence< OUString > FactoryImpl::getSupportedServiceNames() + throw(::com::sun::star::uno::RuntimeException) +{ + return proxyfac_getSupportedServiceNames(); +} + +//============================================================================== +static Reference< XInterface > SAL_CALL proxyfac_create( + Reference< XComponentContext > const & ) + throw (Exception) +{ + Reference< XInterface > xRet; + { + ::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() ); + static WeakReference < XInterface > rwInstance; + xRet = rwInstance; + + if (! xRet.is()) + { + xRet = static_cast< ::cppu::OWeakObject * >(new FactoryImpl); + rwInstance = xRet; + } + } + return xRet; +} + +static ::cppu::ImplementationEntry g_entries [] = +{ + { + proxyfac_create, proxyfac_getImplementationName, + proxyfac_getSupportedServiceNames, ::cppu::createSingleComponentFactory, + &g_moduleCount.modCnt, 0 + }, + { 0, 0, 0, 0, 0, 0 } +}; + +} + +extern "C" +{ + +sal_Bool SAL_CALL component_canUnload( TimeValue * pTime ) +{ + return g_moduleCount.canUnload( &g_moduleCount, pTime ); +} + +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) +{ + return ::cppu::component_getFactoryHelper( + pImplName, pServiceManager, pRegistryKey, g_entries ); +} + +} + diff --git a/stoc/source/proxy_factory/proxyfac.xml b/stoc/source/proxy_factory/proxyfac.xml new file mode 100644 index 000000000000..57f175b70d34 --- /dev/null +++ b/stoc/source/proxy_factory/proxyfac.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + <module-name> proxyfac.uno </module-name> + <component-description> + <author> Daniel Boelzle </author> + <name> com.sun.star.comp.stoc.ProxyFactory </name> + <description> +Specifies a factory object to create proxy objects. +These proxy object represent a given target object and can be +be aggregated. The proxy objects act UNO conform and do NOT provide +original target interfaces on queryInterface() calls. +</description> + <loader-name> com.sun.star.loader.SharedLibrary </loader-name> + <language> C++ </language> + <status value="final"/> + <supported-service> com.sun.star.reflection.ProxyFactory </supported-service> + <service-dependency> ... </service-dependency> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.registry.XSimpleRegistry </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.lang.XSingleComponentFactory </type> + <type> com.sun.star.uno.XComponentContext </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.reflection.XProxyFactory </type> + </component-description> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> sal </project-build-dependency> + <runtime-module-dependency> cppuhelper2$(COM) </runtime-module-dependency> + <runtime-module-dependency> cppu2 </runtime-module-dependency> + <runtime-module-dependency> sal2 </runtime-module-dependency> +</module-description> diff --git a/stoc/source/registry_tdprovider/base.hxx b/stoc/source/registry_tdprovider/base.hxx new file mode 100644 index 000000000000..0e2deed76919 --- /dev/null +++ b/stoc/source/registry_tdprovider/base.hxx @@ -0,0 +1,647 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _STOC_RDBTDP_BASE_HXX +#define _STOC_RDBTDP_BASE_HXX + +#include <osl/diagnose.h> +#include <osl/mutex.hxx> +#include <cppuhelper/weak.hxx> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase2.hxx> +#ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_ +#include <cppuhelper/implementationentry.hxx> +#endif + +#include "registry/refltype.hxx" + +#include <list> +#include <memory> +#include <vector> + +#include <com/sun/star/reflection/XTypeDescription.hpp> +#include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp> +#include <com/sun/star/reflection/XInterfaceTypeDescription.hpp> +#include <com/sun/star/reflection/XInterfaceTypeDescription2.hpp> +#include <com/sun/star/reflection/XCompoundTypeDescription.hpp> +#include <com/sun/star/reflection/XConstantTypeDescription.hpp> +#include <com/sun/star/reflection/XConstantsTypeDescription.hpp> +#include <com/sun/star/reflection/XEnumTypeDescription.hpp> +#include <com/sun/star/reflection/XIndirectTypeDescription.hpp> +#include <com/sun/star/reflection/XServiceConstructorDescription.hpp> +#include <com/sun/star/reflection/XServiceTypeDescription.hpp> +#include <com/sun/star/reflection/XServiceTypeDescription2.hpp> +#include <com/sun/star/reflection/XSingletonTypeDescription2.hpp> +#include <com/sun/star/reflection/XModuleTypeDescription.hpp> +#include <com/sun/star/reflection/XPublished.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> + +using namespace std; +using namespace rtl; +using namespace osl; +using namespace cppu; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::container; +using namespace com::sun::star::reflection; + +//-------------------------------------------------------------------------------------------------- + +extern rtl_StandardModuleCount g_moduleCount; + +namespace stoc_rdbtdp +{ + +com::sun::star::uno::Reference< XTypeDescription > resolveTypedefs( + com::sun::star::uno::Reference< XTypeDescription > const & type); + + +::osl::Mutex & getMutex(); + +//-------------------------------------------------------------------------------------------------- + +typedef ::std::list< ::com::sun::star::uno::Reference< + ::com::sun::star::registry::XRegistryKey > > RegistryKeyList; + +//-------------------------------------------------------------------------------------------------- + +class RegistryKeyCloser +{ +public: + RegistryKeyCloser( const ::com::sun::star::uno::Reference< + ::com::sun::star::registry::XRegistryKey > & xKey ) + : m_xKey( xKey ) {} + ~RegistryKeyCloser() + { if ( m_xKey.is() ) { try { if ( m_xKey->isValid() ) m_xKey->closeKey(); } catch (...) {} } } + + void reset() { m_xKey.clear(); } +private: + ::com::sun::star::uno::Reference< + ::com::sun::star::registry::XRegistryKey > m_xKey; +}; + +//-------------------------------------------------------------------------------------------------- + +// helper to create XTypeDescription instances using typereg::Reader +// (used from Type Provider and Type Description Enumeration implementation) +::com::sun::star::uno::Reference< + ::com::sun::star::reflection::XTypeDescription > +createTypeDescription( + const ::com::sun::star::uno::Sequence< sal_Int8 > & rData, + const ::com::sun::star::uno::Reference< + ::com::sun::star::container::XHierarchicalNameAccess > & xNameAccess, + bool bReturnEmptyRefForUnknownType ); + + +//-------------------------------------------------------------------------------------------------- +inline sal_Int32 getRTValueAsInt32( const RTConstValue & rVal ) +{ + switch (rVal.m_type) + { + case RT_TYPE_BYTE: + return rVal.m_value.aByte; + case RT_TYPE_INT16: + return rVal.m_value.aShort; + case RT_TYPE_UINT16: + return rVal.m_value.aUShort; + case RT_TYPE_INT32: + return rVal.m_value.aLong; + case RT_TYPE_UINT32: + return rVal.m_value.aULong; + default: + OSL_ENSURE( sal_False, "### unexpected value type!" ); + return 0; + } +} +//-------------------------------------------------------------------------------------------------- +inline Any getRTValue( const RTConstValue & rVal ) +{ + switch (rVal.m_type) + { + case RT_TYPE_BOOL: + return Any( &rVal.m_value.aBool, ::getCppuBooleanType() ); + case RT_TYPE_BYTE: + return Any( &rVal.m_value.aByte, ::getCppuType( (const sal_Int8 *)0 ) ); + case RT_TYPE_INT16: + return Any( &rVal.m_value.aShort, ::getCppuType( (const sal_Int16 *)0 ) ); + case RT_TYPE_UINT16: + return Any( &rVal.m_value.aUShort, ::getCppuType( (const sal_uInt16 *)0 ) ); + case RT_TYPE_INT32: + return Any( &rVal.m_value.aLong, ::getCppuType( (const sal_Int32 *)0 ) ); + case RT_TYPE_UINT32: + return Any( &rVal.m_value.aULong, ::getCppuType( (const sal_uInt32 *)0 ) ); + case RT_TYPE_INT64: + return Any( &rVal.m_value.aHyper, ::getCppuType( (const sal_Int64 *)0 ) ); + case RT_TYPE_UINT64: + return Any( &rVal.m_value.aUHyper, ::getCppuType( (const sal_uInt64 *)0 ) ); + case RT_TYPE_FLOAT: + return Any( &rVal.m_value.aFloat, ::getCppuType( (const float *)0 ) ); + case RT_TYPE_DOUBLE: + return Any( &rVal.m_value.aDouble, ::getCppuType( (const double *)0 ) ); + case RT_TYPE_STRING: + { + OUString aStr( rVal.m_value.aString ); + return Any( &aStr, ::getCppuType( (const OUString *)0 ) ); + } + default: + OSL_ENSURE( sal_False, "### unexpected RTValue!" ); + return Any(); + } +} + +//================================================================================================== +class TypeDescriptionImpl : public WeakImplHelper1< XTypeDescription > +{ + TypeClass _eTypeClass; + OUString _aName; + +public: + TypeDescriptionImpl( TypeClass eTypeClass, const OUString & rName ) + : _eTypeClass( eTypeClass ) + , _aName( rName ) + { + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + } + virtual ~TypeDescriptionImpl(); + + // XTypeDescription + virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException); + virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); +}; + +//================================================================================================== +class InterfaceTypeDescriptionImpl: + public WeakImplHelper2< XInterfaceTypeDescription2, XPublished > +{ + com::sun::star::uno::Reference< XHierarchicalNameAccess > _xTDMgr; + Sequence< sal_Int8 > _aBytes; + + OUString _aName; + + Sequence< OUString > _aBaseTypes; + Sequence< com::sun::star::uno::Reference< XTypeDescription > > _xBaseTDs; + Sequence< OUString > _aOptionalBaseTypes; + Sequence< com::sun::star::uno::Reference< XTypeDescription > > + _xOptionalBaseTDs; + + sal_Int32 _nBaseOffset; + Sequence< + com::sun::star::uno::Reference< XInterfaceMemberTypeDescription > > + _members; + bool _membersInit; + + bool _published; + + void checkInterfaceType( + com::sun::star::uno::Reference< XTypeDescription > const & type); + +public: + InterfaceTypeDescriptionImpl( + const com::sun::star::uno::Reference< XHierarchicalNameAccess > & + xTDMgr, + const OUString & rName, const Sequence< OUString > & rBaseTypes, + const Sequence< OUString > & rOptionalBaseTypes, + const Sequence< sal_Int8 > & rBytes, bool published ); + virtual ~InterfaceTypeDescriptionImpl(); + + // XTypeDescription + virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException); + virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); + + // XInterfaceTypeDescription2 + virtual Uik SAL_CALL getUik() throw(::com::sun::star::uno::RuntimeException); + virtual com::sun::star::uno::Reference< XTypeDescription > SAL_CALL + getBaseType() throw(::com::sun::star::uno::RuntimeException); + virtual + Sequence< + com::sun::star::uno::Reference< XInterfaceMemberTypeDescription > > + SAL_CALL getMembers() throw(::com::sun::star::uno::RuntimeException); + + virtual Sequence< com::sun::star::uno::Reference< XTypeDescription > > + SAL_CALL getBaseTypes() throw (RuntimeException); + + virtual Sequence< com::sun::star::uno::Reference< XTypeDescription > > + SAL_CALL getOptionalBaseTypes() throw (RuntimeException); + + virtual sal_Bool SAL_CALL isPublished() + throw (::com::sun::star::uno::RuntimeException) + { return _published; } +}; + +//================================================================================================== +class CompoundTypeDescriptionImpl: + public WeakImplHelper2< XCompoundTypeDescription, XPublished > +{ + com::sun::star::uno::Reference< XHierarchicalNameAccess > _xTDMgr; + TypeClass _eTypeClass; + Sequence< sal_Int8 > _aBytes; + OUString _aName; + + OUString _aBaseType; + com::sun::star::uno::Reference< XTypeDescription > _xBaseTD; + + Sequence< com::sun::star::uno::Reference< XTypeDescription > > * _pMembers; + Sequence< OUString > * _pMemberNames; + + bool _published; + +public: + CompoundTypeDescriptionImpl( + const com::sun::star::uno::Reference< XHierarchicalNameAccess > & + xTDMgr, + TypeClass eTypeClass, + const OUString & rName, const OUString & rBaseName, + const Sequence< sal_Int8 > & rBytes, + bool published ) + : _xTDMgr( xTDMgr ) + , _eTypeClass( eTypeClass ) + , _aBytes( rBytes ) + , _aName( rName ) + , _aBaseType( rBaseName ) + , _pMembers( 0 ) + , _pMemberNames( 0 ) + , _published( published ) + { + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + } + virtual ~CompoundTypeDescriptionImpl(); + + // XTypeDescription + virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException); + virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); + + // XCompoundTypeDescription + virtual com::sun::star::uno::Reference< XTypeDescription > SAL_CALL + getBaseType() throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< com::sun::star::uno::Reference< XTypeDescription > > + SAL_CALL getMemberTypes() throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< OUString > SAL_CALL getMemberNames() throw(::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isPublished() + throw (::com::sun::star::uno::RuntimeException) + { return _published; } +}; + +//================================================================================================== +class EnumTypeDescriptionImpl: + public WeakImplHelper2< XEnumTypeDescription, XPublished > +{ + com::sun::star::uno::Reference< XHierarchicalNameAccess > _xTDMgr; + Sequence< sal_Int8 > _aBytes; + + OUString _aName; + sal_Int32 _nDefaultValue; + + Sequence< OUString > * _pEnumNames; + Sequence< sal_Int32 > * _pEnumValues; + + bool _published; + +public: + EnumTypeDescriptionImpl( + const com::sun::star::uno::Reference< XHierarchicalNameAccess > & + xTDMgr, + const OUString & rName, sal_Int32 nDefaultValue, + const Sequence< sal_Int8 > & rBytes, bool published ) + : _xTDMgr( xTDMgr ) + , _aBytes( rBytes ) + , _aName( rName ) + , _nDefaultValue( nDefaultValue ) + , _pEnumNames( 0 ) + , _pEnumValues( 0 ) + , _published( published ) + { + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + } + virtual ~EnumTypeDescriptionImpl(); + + // XTypeDescription + virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException); + virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); + + // XEnumTypeDescription + virtual sal_Int32 SAL_CALL getDefaultEnumValue() throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< OUString > SAL_CALL getEnumNames() throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< sal_Int32 > SAL_CALL getEnumValues() throw(::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isPublished() + throw (::com::sun::star::uno::RuntimeException) + { return _published; } +}; + +//================================================================================================== +class TypedefTypeDescriptionImpl: + public WeakImplHelper2< XIndirectTypeDescription, XPublished > +{ + com::sun::star::uno::Reference< XHierarchicalNameAccess > _xTDMgr; + OUString _aName; + + OUString _aRefName; + com::sun::star::uno::Reference< XTypeDescription > _xRefTD; + + bool _published; + +public: + TypedefTypeDescriptionImpl( + const com::sun::star::uno::Reference< XHierarchicalNameAccess > & + xTDMgr, + const OUString & rName, const OUString & rRefName, bool published ) + : _xTDMgr( xTDMgr ) + , _aName( rName ) + , _aRefName( rRefName ) + , _published( published ) + { + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + } + virtual ~TypedefTypeDescriptionImpl(); + + // XTypeDescription + virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException); + virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); + + // XIndirectTypeDescription + virtual com::sun::star::uno::Reference< XTypeDescription > SAL_CALL + getReferencedType() throw(::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isPublished() + throw (::com::sun::star::uno::RuntimeException) + { return _published; } +}; + +//================================================================================================== +class ServiceTypeDescriptionImpl: + public WeakImplHelper2< XServiceTypeDescription2, XPublished > +{ + OUString _aName; + Sequence< sal_Int8 > _aBytes; + com::sun::star::uno::Reference< XHierarchicalNameAccess > _xTDMgr; + bool _bInitReferences; + + com::sun::star::uno::Reference< XTypeDescription > _xInterfaceTD; + std::auto_ptr< + Sequence< + com::sun::star::uno::Reference< XServiceConstructorDescription > > > + _pCtors; + Sequence< com::sun::star::uno::Reference< XServiceTypeDescription > > + _aMandatoryServices; + Sequence< com::sun::star::uno::Reference< XServiceTypeDescription > > + _aOptionalServices; + Sequence< com::sun::star::uno::Reference< XInterfaceTypeDescription > > + _aMandatoryInterfaces; + Sequence< com::sun::star::uno::Reference< XInterfaceTypeDescription > > + _aOptionalInterfaces; + std::auto_ptr< + Sequence< com::sun::star::uno::Reference< XPropertyTypeDescription > > > + _pProps; + + bool _published; + +public: + ServiceTypeDescriptionImpl( + const com::sun::star::uno::Reference< XHierarchicalNameAccess > & + xTDMgr, + const OUString & rName, const Sequence< sal_Int8 > & rBytes, + bool published) + : _aName( rName ), _aBytes( rBytes ), _xTDMgr( xTDMgr ), + _bInitReferences( false ), _published( published ) + { + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + } + virtual ~ServiceTypeDescriptionImpl(); + + // XTypeDescription + virtual TypeClass SAL_CALL + getTypeClass() + throw(::com::sun::star::uno::RuntimeException); + virtual OUString SAL_CALL + getName() + throw(::com::sun::star::uno::RuntimeException); + + // XServiceTypeDescription + virtual ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Reference< + ::com::sun::star::reflection::XServiceTypeDescription > > SAL_CALL + getMandatoryServices() + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Reference< + ::com::sun::star::reflection::XServiceTypeDescription > > SAL_CALL + getOptionalServices() + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Reference< + ::com::sun::star::reflection::XInterfaceTypeDescription > > SAL_CALL + getMandatoryInterfaces() + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Reference< + ::com::sun::star::reflection::XInterfaceTypeDescription > > SAL_CALL + getOptionalInterfaces() + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Reference< + ::com::sun::star::reflection::XPropertyTypeDescription > > SAL_CALL + getProperties() + throw (::com::sun::star::uno::RuntimeException); + + // XServiceTypeDescription2 + virtual sal_Bool SAL_CALL isSingleInterfaceBased() + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< XTypeDescription > SAL_CALL + getInterface() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Reference< + ::com::sun::star::reflection::XServiceConstructorDescription > > + SAL_CALL getConstructors() + throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isPublished() + throw (::com::sun::star::uno::RuntimeException) + { return _published; } + +private: + void getReferences() + throw (::com::sun::star::uno::RuntimeException); +}; + +//================================================================================================== +class ModuleTypeDescriptionImpl : public WeakImplHelper1< XModuleTypeDescription > +{ + OUString _aName; + com::sun::star::uno::Reference< XTypeDescriptionEnumerationAccess > _xTDMgr; + + Sequence< com::sun::star::uno::Reference< XTypeDescription > > * _pMembers; + +public: + ModuleTypeDescriptionImpl( + const com::sun::star::uno::Reference< + XTypeDescriptionEnumerationAccess > & xTDMgr, + const OUString & rName ) + : _aName( rName ), _xTDMgr( xTDMgr ), _pMembers( 0 ) + { + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + } + virtual ~ModuleTypeDescriptionImpl(); + + // XTypeDescription + virtual TypeClass SAL_CALL + getTypeClass() + throw( ::com::sun::star::uno::RuntimeException ); + virtual OUString SAL_CALL + getName() + throw( ::com::sun::star::uno::RuntimeException ); + + // XModuleTypeDescription + virtual ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Reference< + ::com::sun::star::reflection::XTypeDescription > > SAL_CALL + getMembers() + throw ( ::com::sun::star::uno::RuntimeException ); +}; + +//================================================================================================== +class ConstantTypeDescriptionImpl : public WeakImplHelper1< XConstantTypeDescription > +{ + OUString _aName; + Any _aValue; + +public: + ConstantTypeDescriptionImpl( const OUString & rName, + const Any & rValue ) + : _aName( rName ), _aValue( rValue ) + { + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + } + virtual ~ConstantTypeDescriptionImpl(); + + // XTypeDescription + virtual TypeClass SAL_CALL + getTypeClass() + throw( ::com::sun::star::uno::RuntimeException ); + virtual OUString SAL_CALL + getName() + throw( ::com::sun::star::uno::RuntimeException ); + + // XConstantTypeDescription + virtual ::com::sun::star::uno::Any SAL_CALL + getConstantValue() + throw ( ::com::sun::star::uno::RuntimeException ); +}; + +//================================================================================================== +class ConstantsTypeDescriptionImpl: + public WeakImplHelper2< XConstantsTypeDescription, XPublished > +{ + OUString _aName; + Sequence< sal_Int8 > _aBytes; + Sequence< com::sun::star::uno::Reference< XConstantTypeDescription > > * + _pMembers; + + bool _published; + +public: + ConstantsTypeDescriptionImpl( const OUString & rName, + const Sequence< sal_Int8 > & rBytes, + bool published ) + : _aName( rName ), _aBytes( rBytes), _pMembers( 0 ), _published( published ) + { + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + } + virtual ~ConstantsTypeDescriptionImpl(); + + // XTypeDescription + virtual TypeClass SAL_CALL + getTypeClass() + throw( ::com::sun::star::uno::RuntimeException ); + virtual OUString SAL_CALL + getName() + throw( ::com::sun::star::uno::RuntimeException ); + + // XConstantsTypeDescription + virtual + Sequence< com::sun::star::uno::Reference< XConstantTypeDescription > > + SAL_CALL getConstants() throw ( RuntimeException ); + + virtual sal_Bool SAL_CALL isPublished() + throw (::com::sun::star::uno::RuntimeException) + { return _published; } +}; + +//================================================================================================== +class SingletonTypeDescriptionImpl: + public WeakImplHelper2< XSingletonTypeDescription2, XPublished > +{ + OUString _aName; + OUString _aBaseName; + com::sun::star::uno::Reference< XHierarchicalNameAccess > _xTDMgr; + com::sun::star::uno::Reference< XTypeDescription > _xInterfaceTD; + com::sun::star::uno::Reference< XServiceTypeDescription > _xServiceTD; + + bool _published; + + void init(); + +public: + SingletonTypeDescriptionImpl( + const com::sun::star::uno::Reference< XHierarchicalNameAccess > & + xTDMgr, + const OUString & rName, const OUString & rBaseName, bool published ) + : _aName( rName ), _aBaseName( rBaseName), _xTDMgr( xTDMgr ), + _published( published ) + { + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + } + virtual ~SingletonTypeDescriptionImpl(); + + // XTypeDescription + virtual TypeClass SAL_CALL + getTypeClass() + throw( ::com::sun::star::uno::RuntimeException ); + virtual OUString SAL_CALL + getName() + throw( ::com::sun::star::uno::RuntimeException ); + + // XSingletonTypeDescription + virtual com::sun::star::uno::Reference< XServiceTypeDescription > SAL_CALL + getService() throw ( ::com::sun::star::uno::RuntimeException ); + + // XSingletonTypeDescription2 + virtual sal_Bool SAL_CALL isInterfaceBased() + throw (::com::sun::star::uno::RuntimeException); + virtual com::sun::star::uno::Reference< XTypeDescription > SAL_CALL + getInterface() throw (::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isPublished() + throw (::com::sun::star::uno::RuntimeException) + { return _published; } +}; + +} + +#endif /* _STOC_RDBTDP_BASE_HXX */ diff --git a/stoc/source/registry_tdprovider/functiondescription.cxx b/stoc/source/registry_tdprovider/functiondescription.cxx new file mode 100644 index 000000000000..b771d0843151 --- /dev/null +++ b/stoc/source/registry_tdprovider/functiondescription.cxx @@ -0,0 +1,115 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include "functiondescription.hxx" + +#include "com/sun/star/container/NoSuchElementException.hpp" +#include "com/sun/star/container/XHierarchicalNameAccess.hpp" +#include "com/sun/star/reflection/XCompoundTypeDescription.hpp" +#include "com/sun/star/uno/Any.hxx" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/TypeClass.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "cppuhelper/implbase1.hxx" +#include "osl/diagnose.h" +#include "osl/mutex.hxx" +#include "registry/reader.hxx" +#include "registry/version.h" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" + +namespace css = com::sun::star; + +using stoc::registry_tdprovider::FunctionDescription; + +FunctionDescription::FunctionDescription( + css::uno::Reference< css::container::XHierarchicalNameAccess > const & + manager, + com::sun::star::uno::Sequence< sal_Int8 > const & bytes, + sal_uInt16 index): + m_manager(manager), m_bytes(bytes), m_index(index), m_exceptionsInit(false) +{} + +FunctionDescription::~FunctionDescription() {} + +css::uno::Sequence< + css::uno::Reference< css::reflection::XCompoundTypeDescription > > +FunctionDescription::getExceptions() const { + { + osl::MutexGuard guard(m_mutex); + if (m_exceptionsInit) { + return m_exceptions; + } + } + typereg::Reader reader(getReader()); + sal_uInt16 n = reader.getMethodExceptionCount(m_index); + css::uno::Sequence< + css::uno::Reference< css::reflection::XCompoundTypeDescription > > + exceptions(n); + for (sal_uInt16 i = 0; i < n; ++i) { + rtl::OUString name( + reader.getMethodExceptionTypeName(m_index, i).replace('/', '.')); + css::uno::Any any; + try { + any = m_manager->getByHierarchicalName(name); + } catch (css::container::NoSuchElementException & e) { + throw new css::uno::RuntimeException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.container.NoSuchElementException: ")) + + e.Message), + css::uno::Reference< css::uno::XInterface >()); //TODO + } + if (!(any >>= exceptions[i]) + || exceptions[i]->getTypeClass() != css::uno::TypeClass_EXCEPTION) + { + throw new css::uno::RuntimeException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("not an exception type: ")) + + name), + css::uno::Reference< css::uno::XInterface >()); //TODO + } + OSL_ASSERT(exceptions[i].is()); + } + osl::MutexGuard guard(m_mutex); + if (!m_exceptionsInit) { + m_exceptions = exceptions; + m_exceptionsInit = true; + } + return m_exceptions; +} + +typereg::Reader FunctionDescription::getReader() const { + return typereg::Reader( + m_bytes.getConstArray(), m_bytes.getLength(), false, TYPEREG_VERSION_1); +} diff --git a/stoc/source/registry_tdprovider/functiondescription.hxx b/stoc/source/registry_tdprovider/functiondescription.hxx new file mode 100644 index 000000000000..d61af71b970f --- /dev/null +++ b/stoc/source/registry_tdprovider/functiondescription.hxx @@ -0,0 +1,86 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_stoc_source_registry_tdprovider_functiondescription_hxx +#define INCLUDED_stoc_source_registry_tdprovider_functiondescription_hxx + +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "osl/mutex.hxx" +#include "sal/types.h" + +namespace com { namespace sun { namespace star { + namespace container { + class XHierarchicalNameAccess; + } + namespace reflection { + class XCompoundTypeDescription; + } +} } } +namespace typereg { class Reader; } + +namespace stoc { namespace registry_tdprovider { + +class FunctionDescription { +public: + FunctionDescription( + com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess > const & + manager, + com::sun::star::uno::Sequence< sal_Int8 > const & bytes, + sal_uInt16 index); + + ~FunctionDescription(); + + com::sun::star::uno::Sequence< + com::sun::star::uno::Reference< + com::sun::star::reflection::XCompoundTypeDescription > > + getExceptions() const; + +protected: + typereg::Reader getReader() const; + + com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess > m_manager; + com::sun::star::uno::Sequence< sal_Int8 > m_bytes; + sal_uInt16 m_index; + + mutable osl::Mutex m_mutex; + mutable com::sun::star::uno::Sequence< + com::sun::star::uno::Reference< + com::sun::star::reflection::XCompoundTypeDescription > > + m_exceptions; + mutable bool m_exceptionsInit; + +private: + FunctionDescription(FunctionDescription &); // not implemented + void operator =(FunctionDescription); // not implemented +}; + +} } + +#endif diff --git a/stoc/source/registry_tdprovider/makefile.mk b/stoc/source/registry_tdprovider/makefile.mk new file mode 100644 index 000000000000..6b59701541bb --- /dev/null +++ b/stoc/source/registry_tdprovider/makefile.mk @@ -0,0 +1,61 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME= stoc +TARGET = regtypeprov +ENABLE_EXCEPTIONS=TRUE +BOOTSTRAP_SERVICE=TRUE +UNOUCROUT= $(OUT)$/inc$/bootstrap + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# ------------------------------------------------------------------ + +SLOFILES= \ + $(SLO)$/tdprovider.obj \ + $(SLO)$/td.obj \ + $(SLO)$/tdef.obj \ + $(SLO)$/tdenum.obj \ + $(SLO)$/tdcomp.obj \ + $(SLO)$/tdconsts.obj \ + $(SLO)$/tdiface.obj \ + $(SLO)$/tdmodule.obj \ + $(SLO)$/tdprop.obj \ + $(SLO)$/tdservice.obj \ + $(SLO)$/tdsingleton.obj \ + $(SLO)$/rdbtdp_tdenumeration.obj \ + $(SLO)$/functiondescription.obj \ + $(SLO)$/methoddescription.obj \ + $(SLO)$/structtypedescription.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/stoc/source/registry_tdprovider/methoddescription.cxx b/stoc/source/registry_tdprovider/methoddescription.cxx new file mode 100644 index 000000000000..7301f84248c5 --- /dev/null +++ b/stoc/source/registry_tdprovider/methoddescription.cxx @@ -0,0 +1,144 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include "methoddescription.hxx" + +#include "com/sun/star/container/NoSuchElementException.hpp" +#include "com/sun/star/container/XHierarchicalNameAccess.hpp" +#include "com/sun/star/reflection/XParameter.hpp" +#include "com/sun/star/reflection/XTypeDescription.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/weak.hxx" +#include "osl/mutex.hxx" +#include "registry/reader.hxx" +#include "registry/types.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" + +namespace css = com::sun::star; + +using stoc::registry_tdprovider::MethodDescription; + +namespace { + +class Parameter: public cppu::WeakImplHelper1< css::reflection::XParameter > { +public: + Parameter( + css::uno::Reference< css::container::XHierarchicalNameAccess > const & + manager, + rtl::OUString const & name, rtl::OUString const & typeName, + RTParamMode mode, sal_Int32 position): + m_manager(manager), m_name(name), + m_typeName(typeName.replace('/', '.')), m_mode(mode), + m_position(position) {} + + virtual ~Parameter() {} + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException) + { return m_name; } + + virtual css::uno::Reference< css::reflection::XTypeDescription > SAL_CALL + getType() throw (css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isIn() throw (css::uno::RuntimeException) + { return (m_mode & RT_PARAM_IN) != 0; } + + virtual sal_Bool SAL_CALL isOut() throw (css::uno::RuntimeException) + { return (m_mode & RT_PARAM_OUT) != 0; } + + virtual sal_Int32 SAL_CALL getPosition() throw (css::uno::RuntimeException) + { return m_position; } + + virtual sal_Bool SAL_CALL isRestParameter() + throw (css::uno::RuntimeException) + { return (m_mode & RT_PARAM_REST) != 0; } + +private: + Parameter(Parameter &); // not implemented + void operator =(Parameter); // not implemented + + css::uno::Reference< css::container::XHierarchicalNameAccess > m_manager; + rtl::OUString m_name; + rtl::OUString m_typeName; + RTParamMode m_mode; + sal_Int32 m_position; +}; + +css::uno::Reference< css::reflection::XTypeDescription > Parameter::getType() + throw (css::uno::RuntimeException) +{ + try { + return css::uno::Reference< css::reflection::XTypeDescription >( + m_manager->getByHierarchicalName(m_typeName), + css::uno::UNO_QUERY_THROW); + } catch (css::container::NoSuchElementException & e) { + throw new css::uno::RuntimeException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.container.NoSuchElementException: ")) + + e.Message), + static_cast< cppu::OWeakObject * >(this)); + } +} + +} + +MethodDescription::MethodDescription( + css::uno::Reference< css::container::XHierarchicalNameAccess > const & + manager, + rtl::OUString const & name, + com::sun::star::uno::Sequence< sal_Int8 > const & bytes, + sal_uInt16 index): + FunctionDescription(manager, bytes, index), m_name(name), + m_parametersInit(false) +{} + +MethodDescription::~MethodDescription() {} + +css::uno::Sequence< css::uno::Reference< css::reflection::XParameter > > +MethodDescription::getParameters() const { + osl::MutexGuard guard(m_mutex); + if (!m_parametersInit) { + typereg::Reader reader(getReader()); + sal_uInt16 n = reader.getMethodParameterCount(m_index); + m_parameters.realloc(n); + for (sal_uInt16 i = 0; i < n; ++i) { + m_parameters[i] = new Parameter( + m_manager, reader.getMethodParameterName(m_index, i), + reader.getMethodParameterTypeName(m_index, i), + reader.getMethodParameterFlags(m_index, i), i); + } + m_parametersInit = true; + } + return m_parameters; +} diff --git a/stoc/source/registry_tdprovider/methoddescription.hxx b/stoc/source/registry_tdprovider/methoddescription.hxx new file mode 100644 index 000000000000..8d46eced73ac --- /dev/null +++ b/stoc/source/registry_tdprovider/methoddescription.hxx @@ -0,0 +1,82 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_stoc_source_registry_tdprovider_methoddescription_hxx +#define INCLUDED_stoc_source_registry_tdprovider_methoddescription_hxx + +#include "functiondescription.hxx" + +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "rtl/ustring.hxx" +#include "sal/types.h" + +namespace com { namespace sun { namespace star { + namespace container { + class XHierarchicalNameAccess; + } + namespace reflection { + class XParameter; + } +} } } +namespace typereg { class Reader; } + +namespace stoc { namespace registry_tdprovider { + +class MethodDescription: public FunctionDescription { +public: + MethodDescription( + com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess > const & + manager, + rtl::OUString const & name, + com::sun::star::uno::Sequence< sal_Int8 > const & bytes, + sal_uInt16 index); + + ~MethodDescription(); + + rtl::OUString getName() const { return m_name; } + + com::sun::star::uno::Sequence< + com::sun::star::uno::Reference< + com::sun::star::reflection::XParameter > > + getParameters() const; + +private: + MethodDescription(MethodDescription &); // not implemented + void operator =(MethodDescription); // not implemented + + rtl::OUString m_name; + mutable com::sun::star::uno::Sequence< + com::sun::star::uno::Reference< + com::sun::star::reflection::XParameter > > m_parameters; + mutable bool m_parametersInit; +}; + +} } + +#endif diff --git a/stoc/source/registry_tdprovider/rdbtdp_tdenumeration.cxx b/stoc/source/registry_tdprovider/rdbtdp_tdenumeration.cxx new file mode 100644 index 000000000000..7104fbf57d92 --- /dev/null +++ b/stoc/source/registry_tdprovider/rdbtdp_tdenumeration.cxx @@ -0,0 +1,643 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +//========================================================================= +// Todo: +// +// - closeKey() calls (according to JSC not really needed because XRegistry +// implementation closes key in it's dtor. +// +//========================================================================= +#include <osl/diagnose.h> +#include <rtl/ustrbuf.hxx> +#include "com/sun/star/reflection/XPublished.hpp" +#include "cppuhelper/implbase1.hxx" +#include "registry/reader.hxx" +#include "registry/version.h" +#include "base.hxx" +#include "rdbtdp_tdenumeration.hxx" + +using namespace com::sun::star; + +namespace { + +class IndividualConstantTypeDescriptionImpl: + public cppu::ImplInheritanceHelper1< + stoc_rdbtdp::ConstantTypeDescriptionImpl, + com::sun::star::reflection::XPublished > +{ +public: + IndividualConstantTypeDescriptionImpl( + rtl::OUString const & name, com::sun::star::uno::Any const & value, + bool published): + cppu::ImplInheritanceHelper1< + stoc_rdbtdp::ConstantTypeDescriptionImpl, + com::sun::star::reflection::XPublished >(name, value), + m_published(published) {} + + virtual sal_Bool SAL_CALL isPublished() + throw (::com::sun::star::uno::RuntimeException) + { return m_published; } + +private: + bool m_published; +}; + +} + +namespace stoc_rdbtdp +{ + +//========================================================================= +//========================================================================= +// +// TypeDescriptionEnumerationImpl Implementation. +// +//========================================================================= +//========================================================================= + +// static +rtl::Reference< TypeDescriptionEnumerationImpl > +TypeDescriptionEnumerationImpl::createInstance( + const uno::Reference< container::XHierarchicalNameAccess > & xTDMgr, + const rtl::OUString & rModuleName, + const uno::Sequence< uno::TypeClass > & rTypes, + reflection::TypeDescriptionSearchDepth eDepth, + const RegistryKeyList & rBaseKeys ) + throw ( reflection::NoSuchTypeNameException, + reflection::InvalidTypeNameException, + uno::RuntimeException ) +{ + if ( rModuleName.getLength() == 0 ) + { + // Enumeration for root requested. + return rtl::Reference< TypeDescriptionEnumerationImpl >( + new TypeDescriptionEnumerationImpl( + xTDMgr, rBaseKeys, rTypes, eDepth ) ); + } + + RegistryKeyList aModuleKeys; + + rtl::OUString aKey( rModuleName.replace( '.', '/' ) ); + + bool bOpenKeySucceeded = false; + + const RegistryKeyList::const_iterator end = rBaseKeys.end(); + RegistryKeyList::const_iterator it = rBaseKeys.begin(); + + while ( it != end ) + { + uno::Reference< registry::XRegistryKey > xKey; + try + { + xKey = (*it)->openKey( aKey ); + if ( xKey.is() ) + { + // closes key in it's dtor (which is + // called even in case of exceptions). + RegistryKeyCloser aCloser( xKey ); + + if ( xKey->isValid() ) + { + bOpenKeySucceeded = true; + + if ( xKey->getValueType() + == registry::RegistryValueType_BINARY ) + { + uno::Sequence< sal_Int8 > aBytes( + xKey->getBinaryValue() ); + + typereg::Reader aReader( + aBytes.getConstArray(), aBytes.getLength(), false, + TYPEREG_VERSION_1); + + rtl::OUString aName( + aReader.getTypeName().replace( '/', '.' ) ); + + if ( aReader.getTypeClass() == RT_TYPE_MODULE ) + { + // Do not close xKey! + aCloser.reset(); + + aModuleKeys.push_back( xKey ); + } + } + } + else + { + OSL_ENSURE( + sal_False, + "TypeDescriptionEnumerationImpl::createInstance " + "- Invalid registry key!" ); + } + } + } + catch ( registry::InvalidRegistryException const & ) + { + // openKey, getValueType, getBinaryValue + + OSL_ENSURE( sal_False, + "TypeDescriptionEnumerationImpl::createInstance " + "- Caught InvalidRegistryException!" ); + } + + it++; + } + + if ( !bOpenKeySucceeded ) + throw reflection::NoSuchTypeNameException(); + + if ( aModuleKeys.size() == 0 ) + throw reflection::InvalidTypeNameException(); + + return rtl::Reference< TypeDescriptionEnumerationImpl >( + new TypeDescriptionEnumerationImpl( + xTDMgr, aModuleKeys, rTypes, eDepth ) ); +} + +//========================================================================= +TypeDescriptionEnumerationImpl::TypeDescriptionEnumerationImpl( + const uno::Reference< container::XHierarchicalNameAccess > & xTDMgr, + const RegistryKeyList & rModuleKeys, + const uno::Sequence< uno::TypeClass > & rTypes, + reflection::TypeDescriptionSearchDepth eDepth ) +: m_aModuleKeys( rModuleKeys ), + m_aTypes( rTypes ), + m_eDepth( eDepth ), + m_xTDMgr( xTDMgr ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); +} + +//========================================================================= +// virtual +TypeDescriptionEnumerationImpl::~TypeDescriptionEnumerationImpl() +{ + RegistryKeyList::const_iterator it = m_aModuleKeys.begin(); + RegistryKeyList::const_iterator end = m_aModuleKeys.end(); +/* + @@@ in case we enumerate root and queryMore was never called, then + m_aModuleKeys contains open root keys which where passed from + tdprov and must not be closed by us. + + while ( it != end ) + { + try + { + if ( (*it)->isValid() ) + (*it)->closeKey(); + } + catch (...) + { + // No exceptions from dtors, please! + OSL_ENSURE( sal_False, + "TypeDescriptionEnumerationImpl::~TypeDescriptionEnumerationImpl " + "- Caught exception!" ); + } + + it++; + } +*/ + it = m_aCurrentModuleSubKeys.begin(); + end = m_aCurrentModuleSubKeys.end(); + while ( it != end ) + { + try + { + if ( (*it)->isValid() ) + (*it)->closeKey(); + } + catch (Exception &) + { + // No exceptions from dtors, please! + OSL_ENSURE( sal_False, + "TypeDescriptionEnumerationImpl::~TypeDescriptionEnumerationImpl " + "- Caught exception!" ); + } + + it++; + } + + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +//========================================================================= +// +// XEnumeration (base of XTypeDescriptionEnumeration) methods +// +//========================================================================= + +// virtual +sal_Bool SAL_CALL TypeDescriptionEnumerationImpl::hasMoreElements() + throw ( uno::RuntimeException ) +{ + return queryMore(); +} + +//========================================================================= +// virtual +uno::Any SAL_CALL TypeDescriptionEnumerationImpl::nextElement() + throw ( container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException ) +{ + return uno::Any( uno::makeAny( nextTypeDescription() ) ); +} + +//========================================================================= +// +// XTypeDescriptionEnumeration methods +// +//========================================================================= + +// virtual +uno::Reference< reflection::XTypeDescription > SAL_CALL +TypeDescriptionEnumerationImpl::nextTypeDescription() + throw ( container::NoSuchElementException, + uno::RuntimeException ) +{ + uno::Reference< reflection::XTypeDescription > xTD( queryNext() ); + + if ( xTD.is() ) + return xTD; + + throw container::NoSuchElementException( + rtl::OUString::createFromAscii( + "No further elements in enumeration!" ), + static_cast< cppu::OWeakObject * >( this ) ); +} + +//========================================================================= +bool TypeDescriptionEnumerationImpl::match( + RTTypeClass eType1, uno::TypeClass eType2 ) +{ + switch ( eType1 ) + { + case RT_TYPE_INTERFACE: + return eType2 == uno::TypeClass_INTERFACE; + + case RT_TYPE_MODULE: + return eType2 == uno::TypeClass_MODULE; + + case RT_TYPE_STRUCT: + return eType2 == uno::TypeClass_STRUCT; + + case RT_TYPE_ENUM: + return eType2 == uno::TypeClass_ENUM; + + case RT_TYPE_EXCEPTION: + return eType2 == uno::TypeClass_EXCEPTION; + + case RT_TYPE_TYPEDEF: + return eType2 == uno::TypeClass_TYPEDEF; + + case RT_TYPE_SERVICE: + return eType2 == uno::TypeClass_SERVICE; + + case RT_TYPE_SINGLETON: + return eType2 == uno::TypeClass_SINGLETON; + + case RT_TYPE_CONSTANTS: + return eType2 == uno::TypeClass_CONSTANTS; + + case RT_TYPE_UNION: + return eType2 == uno::TypeClass_UNION; + + default: + return false; + } +} + +//========================================================================= +bool TypeDescriptionEnumerationImpl::queryMore() +{ + osl::MutexGuard aGuard( m_aMutex ); + + for (;;) + { + if ( !m_aCurrentModuleSubKeys.empty() || !m_aTypeDescs.empty() ) + { + // Okay, there is at least one more element. + return true; + } + + if ( m_aModuleKeys.empty() ) + { + // No module keys (therefore no elements) left. + return false; + } + + // Note: m_aCurrentModuleSubKeys is always empty AND m_aModuleKeys is + // never empty when ariving here. + // ==> select new module key, fill m_aCurrentModuleSubKeys + + uno::Sequence< uno::Reference< registry::XRegistryKey > > aKeys; + try + { + aKeys = m_aModuleKeys.front()->openKeys(); + for ( sal_Int32 n = 0; n < aKeys.getLength(); ++n ) + { + uno::Reference< registry::XRegistryKey > xKey = aKeys[ n ]; + + // closes key in it's dtor (which is + // called even in case of exceptions). + RegistryKeyCloser aCloser( xKey ); + + try + { + if ( xKey->isValid() ) + { + if ( xKey->getValueType() + == registry::RegistryValueType_BINARY ) + { + bool bIncludeIt = (m_aTypes.getLength() == 0); + bool bNeedTypeClass = + ((m_aTypes.getLength() > 0) || + (m_eDepth + == reflection::TypeDescriptionSearchDepth_INFINITE)); + if ( bNeedTypeClass ) + { + uno::Sequence< sal_Int8 > aBytes( + xKey->getBinaryValue() ); + + typereg::Reader aReader( + aBytes.getConstArray(), aBytes.getLength(), + false, TYPEREG_VERSION_1); + + RTTypeClass eTypeClass = aReader.getTypeClass(); + + // Does key match requested types? Empty + // sequence means include all. + if ( m_aTypes.getLength() > 0 ) + { + for ( sal_Int32 m = 0; + m < m_aTypes.getLength(); + ++m ) + { + if ( match(eTypeClass, m_aTypes[ m ]) ) + { + bIncludeIt = true; + break; + } + } + } + + if ( m_eDepth == + reflection::TypeDescriptionSearchDepth_INFINITE ) + { + if ( eTypeClass == RT_TYPE_MODULE ) + { + // Do not close xKey! + aCloser.reset(); + + // Remember new module key. + m_aModuleKeys.push_back( xKey ); + } + } + } + + if ( bIncludeIt ) + { + // Do not close xKey! + aCloser.reset(); + + m_aCurrentModuleSubKeys.push_back( xKey ); + } + } + } + else + { + OSL_ENSURE( sal_False, + "TypeDescriptionEnumerationImpl::queryMore " + "- Invalid registry key!" ); + } + + } + catch ( registry::InvalidRegistryException const & ) + { + // getValueType, getBinaryValue + + OSL_ENSURE( sal_False, + "TypeDescriptionEnumerationImpl::queryMore " + "- Caught InvalidRegistryException!" ); + + // Don't stop iterating! + } + } + } + catch ( registry::InvalidRegistryException const & ) + { + // openKeys + + for ( sal_Int32 n = 0; n < aKeys.getLength(); ++n ) + { + try + { + aKeys[ n ]->closeKey(); + } + catch ( registry::InvalidRegistryException const & ) + { + OSL_ENSURE( sal_False, + "TypeDescriptionEnumerationImpl::queryMore " + "- Caught InvalidRegistryException!" ); + } + } + } + + ///////////////////////////////////////////////////////////////////// + // Special handling for constants contained directly in module. + ///////////////////////////////////////////////////////////////////// + + // Constants requested? + bool bIncludeConstants = ( m_aTypes.getLength() == 0 ); + if ( !bIncludeConstants ) + { + for ( sal_Int32 m = 0; m < m_aTypes.getLength(); ++m ) + { + if ( m_aTypes[ m ] == uno::TypeClass_CONSTANT ) + { + bIncludeConstants = true; + break; + } + } + + } + + if ( bIncludeConstants ) + { + if ( m_aModuleKeys.front()->getValueType() + == registry::RegistryValueType_BINARY ) + { + try + { + uno::Sequence< sal_Int8 > aBytes( + m_aModuleKeys.front()->getBinaryValue() ); + + typereg::Reader aReader( + aBytes.getConstArray(), aBytes.getLength(), false, + TYPEREG_VERSION_1); + + if ( aReader.getTypeClass() == RT_TYPE_MODULE ) + { + sal_uInt16 nFields = aReader.getFieldCount(); + while ( nFields-- ) + { + rtl::OUStringBuffer aName( + aReader.getTypeName().replace( '/', '.' ) ); + aName.appendAscii( "." ); + aName.append( aReader.getFieldName( nFields ) ); + + uno::Any aValue( + getRTValue( + aReader.getFieldValue( nFields ) ) ); + + m_aTypeDescs.push_back( + new IndividualConstantTypeDescriptionImpl( + aName.makeStringAndClear(), aValue, + ( ( aReader.getFieldFlags( nFields ) + & RT_ACCESS_PUBLISHED ) + != 0 ) ) ); + } + } + } + catch ( registry::InvalidRegistryException const & ) + { + // getBinaryValue + + OSL_ENSURE( sal_False, + "TypeDescriptionEnumerationImpl::queryMore " + "- Caught InvalidRegistryException!" ); + } + } + } + + ///////////////////////////////////////////////////////////////////// + +/* + @@@ m_aModuleKeys.front() may have open sub keys (may be contained in + both m_aModuleKeys and m_aCurrentModuleSubKeys)! + + try + { + m_aModuleKeys.front()->closeKey(); + } + catch ( registry::InvalidRegistryException const & ) + { + OSL_ENSURE( sal_False, + "TypeDescriptionEnumerationImpl::queryMore " + "- Caught InvalidRegistryException!" ); + } +*/ + // We're done with this module key, even if there were errors. + m_aModuleKeys.pop_front(); + } + + // unreachable +} + +//========================================================================= +uno::Reference< reflection::XTypeDescription > +TypeDescriptionEnumerationImpl::queryNext() +{ + osl::MutexGuard aGuard( m_aMutex ); + + for (;;) + { + if ( !queryMore() ) + return uno::Reference< reflection::XTypeDescription >(); + + uno::Reference< reflection::XTypeDescription > xTD; + + if ( !m_aTypeDescs.empty() ) + { + xTD = m_aTypeDescs.front(); + m_aTypeDescs.pop_front(); + return xTD; + } + + // Note: xKey is already opened. + uno::Reference< registry::XRegistryKey > + xKey( m_aCurrentModuleSubKeys.front() ); +/* + @@@ xKey may still be contained in m_aModuleKeys, too + + // closes key in it's dtor (which is + // called even in case of exceptions). + RegistryKeyCloser aCloser( xKey ); +*/ + try + { + { + if ( xKey->isValid() ) + { + if ( xKey->getValueType() + == registry::RegistryValueType_BINARY ) + { + uno::Sequence< sal_Int8 > aBytes( + xKey->getBinaryValue() ); + + xTD = createTypeDescription( aBytes, + m_xTDMgr, + false ); + OSL_ENSURE( xTD.is(), + "TypeDescriptionEnumerationImpl::queryNext " + "- No XTypeDescription created!" ); + } + } + else + { + OSL_ENSURE( sal_False, + "TypeDescriptionEnumerationImpl::queryNext " + "- Invalid registry key!" ); + } + } + } + catch ( registry::InvalidRegistryException const & ) + { + // getValueType, getBinaryValue + + OSL_ENSURE( sal_False, + "TypeDescriptionEnumerationImpl::queryNext " + "- Caught InvalidRegistryException!" ); + } + + // We're done with this key, even if there were errors. + m_aCurrentModuleSubKeys.pop_front(); + + if ( xTD.is() ) + return xTD; + + // next try... + + } // for (;;) +} + +} // namespace stoc_rdbtdp + diff --git a/stoc/source/registry_tdprovider/rdbtdp_tdenumeration.hxx b/stoc/source/registry_tdprovider/rdbtdp_tdenumeration.hxx new file mode 100644 index 000000000000..7e2c84840aae --- /dev/null +++ b/stoc/source/registry_tdprovider/rdbtdp_tdenumeration.hxx @@ -0,0 +1,116 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _STOC_RDBTDP_TDENUMERATION_HXX +#define _STOC_RDBTDP_TDENUMERATION_HXX + +#include <list> +#include <osl/mutex.hxx> +#include <rtl/ref.hxx> +#include <registry/refltype.hxx> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/reflection/InvalidTypeNameException.hpp> +#include <com/sun/star/reflection/NoSuchTypeNameException.hpp> +#include <com/sun/star/reflection/TypeDescriptionSearchDepth.hpp> +#include <com/sun/star/reflection/XTypeDescriptionEnumeration.hpp> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/TypeClass.hpp> +#include <cppuhelper/implbase1.hxx> +#include "base.hxx" + +namespace stoc_rdbtdp +{ + +typedef ::std::list< ::com::sun::star::uno::Reference< + ::com::sun::star::reflection::XTypeDescription > > TypeDescriptionList; + +class TypeDescriptionEnumerationImpl + : public cppu::WeakImplHelper1< + com::sun::star::reflection::XTypeDescriptionEnumeration > +{ +public: + static rtl::Reference< TypeDescriptionEnumerationImpl > createInstance( + const ::com::sun::star::uno::Reference< + ::com::sun::star::container::XHierarchicalNameAccess > & xTDMgr, + const rtl::OUString & rModuleName, + const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::TypeClass > & rTypes, + ::com::sun::star::reflection::TypeDescriptionSearchDepth eDepth, + const RegistryKeyList & rBaseKeys ) + throw ( ::com::sun::star::reflection::NoSuchTypeNameException, + ::com::sun::star::reflection::InvalidTypeNameException, + ::com::sun::star::uno::RuntimeException ); + + virtual ~TypeDescriptionEnumerationImpl(); + + // XEnumeration (base of XTypeDescriptionEnumeration) + virtual sal_Bool SAL_CALL hasMoreElements() + throw ( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Any SAL_CALL nextElement() + throw ( ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException ); + + // XTypeDescriptionEnumeration + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::reflection::XTypeDescription > SAL_CALL + nextTypeDescription() + throw ( ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException ); + +private: + // Note: keys must be open (XRegistryKey->openKey(...)). + TypeDescriptionEnumerationImpl( + const ::com::sun::star::uno::Reference< + ::com::sun::star::container::XHierarchicalNameAccess > & xTDMgr, + const RegistryKeyList & rModuleKeys, + const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::TypeClass > & rTypes, + ::com::sun::star::reflection::TypeDescriptionSearchDepth eDepth ); + + static bool match( ::RTTypeClass eType1, + ::com::sun::star::uno::TypeClass eType2 ); + bool queryMore(); + ::com::sun::star::uno::Reference< + ::com::sun::star::reflection::XTypeDescription > queryNext(); + + // members + osl::Mutex m_aMutex; + RegistryKeyList m_aModuleKeys; + RegistryKeyList m_aCurrentModuleSubKeys; + TypeDescriptionList m_aTypeDescs; + ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::TypeClass > m_aTypes; + ::com::sun::star::reflection::TypeDescriptionSearchDepth m_eDepth; + ::com::sun::star::uno::Reference< + ::com::sun::star::container::XHierarchicalNameAccess > m_xTDMgr; +}; + +} // namespace stoc_rdbtdp + +#endif /* _STOC_RDBTDP_TDENUMERATION_HXX */ + diff --git a/stoc/source/registry_tdprovider/structtypedescription.cxx b/stoc/source/registry_tdprovider/structtypedescription.cxx new file mode 100644 index 000000000000..52cc247fae2e --- /dev/null +++ b/stoc/source/registry_tdprovider/structtypedescription.cxx @@ -0,0 +1,139 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include "structtypedescription.hxx" + +#include "base.hxx" + +#include "com/sun/star/reflection/XTypeDescription.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/TypeClass.hpp" +#include "cppuhelper/weak.hxx" +#include "osl/diagnose.h" +#include "registry/reader.hxx" +#include "registry/types.h" +#include "registry/version.h" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" + +#include <new> + +namespace css = com::sun::star; +using stoc::registry_tdprovider::StructTypeDescription; + +StructTypeDescription::StructTypeDescription( + css::uno::Reference< css::container::XHierarchicalNameAccess > const & + manager, + rtl::OUString const & name, rtl::OUString const & baseTypeName, + css::uno::Sequence< sal_Int8 > const & data, bool published): + m_data(data), + m_base( + new stoc_rdbtdp::CompoundTypeDescriptionImpl( + manager, css::uno::TypeClass_STRUCT, name, baseTypeName, data, + published)) +{} + +StructTypeDescription::~StructTypeDescription() +{} + +css::uno::TypeClass StructTypeDescription::getTypeClass() + throw (css::uno::RuntimeException) +{ + return m_base->getTypeClass(); +} + +rtl::OUString StructTypeDescription::getName() + throw (css::uno::RuntimeException) +{ + return m_base->getName(); +} + +css::uno::Reference< css::reflection::XTypeDescription > +StructTypeDescription::getBaseType() throw (css::uno::RuntimeException) +{ + return m_base->getBaseType(); +} + +css::uno::Sequence< css::uno::Reference< css::reflection::XTypeDescription > > +StructTypeDescription::getMemberTypes() throw (css::uno::RuntimeException) +{ + return m_base->getMemberTypes(); +} + +css::uno::Sequence< rtl::OUString > StructTypeDescription::getMemberNames() + throw (css::uno::RuntimeException) +{ + return m_base->getMemberNames(); +} + +css::uno::Sequence< rtl::OUString > StructTypeDescription::getTypeParameters() + throw (css::uno::RuntimeException) +{ + try { + typereg::Reader reader( + m_data.getConstArray(), m_data.getLength(), false, + TYPEREG_VERSION_1); + OSL_ASSERT(reader.isValid()); + sal_uInt16 n = reader.getReferenceCount(); + css::uno::Sequence< rtl::OUString > parameters(n); + for (sal_uInt16 i = 0; i < n; ++i) { + if (reader.getReferenceFlags(i) != RT_ACCESS_INVALID + || reader.getReferenceSort(i) != RT_REF_TYPE_PARAMETER) + { + throw css::uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "type parameter of polymorphic struct type template" + " not RT_ACCESS_INVALID/RT_REF_TYPE_PARAMETER")), + static_cast< cppu::OWeakObject * >(this)); + } + parameters[i] = reader.getReferenceTypeName(i); + } + return parameters; + } catch (std::bad_alloc &) { + throw css::uno::RuntimeException( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("std::bad_alloc")), + static_cast< cppu::OWeakObject * >(this)); + } +} + +css::uno::Sequence< css::uno::Reference< css::reflection::XTypeDescription > > +StructTypeDescription::getTypeArguments() throw (css::uno::RuntimeException) +{ + return css::uno::Sequence< + css::uno::Reference< css::reflection::XTypeDescription > >(); +} + +sal_Bool StructTypeDescription::isPublished() throw (css::uno::RuntimeException) +{ + return m_base->isPublished(); +} diff --git a/stoc/source/registry_tdprovider/structtypedescription.hxx b/stoc/source/registry_tdprovider/structtypedescription.hxx new file mode 100644 index 000000000000..ba2ce701992e --- /dev/null +++ b/stoc/source/registry_tdprovider/structtypedescription.hxx @@ -0,0 +1,105 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_stoc_source_registry_tdprovider_structtypedescription_hxx +#define INCLUDED_stoc_source_registry_tdprovider_structtypedescription_hxx + +#include "com/sun/star/reflection/XPublished.hpp" +#include "com/sun/star/reflection/XStructTypeDescription.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "cppuhelper/implbase2.hxx" +#include "rtl/ref.hxx" +#include "sal/types.h" + +namespace com { namespace sun { namespace star { + namespace container { class XHierarchicalNameAccess; } + namespace reflection { class XCompoundTypeDescription; } +} } } +namespace rtl { class OUString; } +namespace stoc_rdbtdp { class CompoundTypeDescriptionImpl; } + +namespace stoc { namespace registry_tdprovider { + +class StructTypeDescription: + public cppu::WeakImplHelper2< + com::sun::star::reflection::XStructTypeDescription, + com::sun::star::reflection::XPublished > +{ +public: + StructTypeDescription( + com::sun::star::uno::Reference< + com::sun::star::container::XHierarchicalNameAccess > const & + manager, + rtl::OUString const & name, rtl::OUString const & baseTypeName, + com::sun::star::uno::Sequence< sal_Int8 > const & data, bool published); + + virtual ~StructTypeDescription(); + + virtual com::sun::star::uno::TypeClass SAL_CALL getTypeClass() + throw (com::sun::star::uno::RuntimeException); + + virtual rtl::OUString SAL_CALL getName() + throw (com::sun::star::uno::RuntimeException); + + virtual + com::sun::star::uno::Reference< + com::sun::star::reflection::XTypeDescription > + SAL_CALL getBaseType() throw (com::sun::star::uno::RuntimeException); + + virtual + com::sun::star::uno::Sequence< + com::sun::star::uno::Reference< + com::sun::star::reflection::XTypeDescription > > + SAL_CALL getMemberTypes() throw (com::sun::star::uno::RuntimeException); + + virtual com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL + getMemberNames() throw (com::sun::star::uno::RuntimeException); + + virtual com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL + getTypeParameters() throw (com::sun::star::uno::RuntimeException); + + virtual + com::sun::star::uno::Sequence< + com::sun::star::uno::Reference< + com::sun::star::reflection::XTypeDescription > > + SAL_CALL getTypeArguments() throw (com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isPublished() + throw (com::sun::star::uno::RuntimeException); + +private: + StructTypeDescription(StructTypeDescription &); // not implemented + void operator =(StructTypeDescription); // not implemented + + com::sun::star::uno::Sequence< sal_Int8 > m_data; + rtl::Reference< stoc_rdbtdp::CompoundTypeDescriptionImpl > m_base; +}; + +} } + +#endif diff --git a/stoc/source/registry_tdprovider/td.cxx b/stoc/source/registry_tdprovider/td.cxx new file mode 100644 index 000000000000..27a5a936d54b --- /dev/null +++ b/stoc/source/registry_tdprovider/td.cxx @@ -0,0 +1,80 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include "osl/doublecheckedlocking.h" +#include "base.hxx" + +namespace stoc_rdbtdp +{ + +//------------------------------------------------------------------------------ +::osl::Mutex & getMutex() +{ + static ::osl::Mutex * s_pmutex = 0; + if (s_pmutex == 0) + { + ::osl::MutexGuard guard( ::osl::Mutex::getGlobalMutex() ); + if (s_pmutex == 0) + { + static ::osl::Mutex s_mutex; + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + s_pmutex = &s_mutex; + } + } + else + { + OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER(); + } + return *s_pmutex; +} + + +TypeDescriptionImpl::~TypeDescriptionImpl() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +// XTypeDescription +//__________________________________________________________________________________________________ +TypeClass TypeDescriptionImpl::getTypeClass() + throw(::com::sun::star::uno::RuntimeException) +{ + return _eTypeClass; +} +//__________________________________________________________________________________________________ +OUString TypeDescriptionImpl::getName() + throw(::com::sun::star::uno::RuntimeException) +{ + return _aName; +} + +} + + diff --git a/stoc/source/registry_tdprovider/tdcomp.cxx b/stoc/source/registry_tdprovider/tdcomp.cxx new file mode 100644 index 000000000000..d7ca4887ee7c --- /dev/null +++ b/stoc/source/registry_tdprovider/tdcomp.cxx @@ -0,0 +1,187 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include "base.hxx" + +#include "registry/reader.hxx" +#include "registry/version.h" + +namespace stoc_rdbtdp +{ + +//__________________________________________________________________________________________________ +CompoundTypeDescriptionImpl::~CompoundTypeDescriptionImpl() +{ + delete _pMembers; + delete _pMemberNames; + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +// XTypeDescription +//__________________________________________________________________________________________________ +TypeClass CompoundTypeDescriptionImpl::getTypeClass() + throw(::com::sun::star::uno::RuntimeException) +{ + return _eTypeClass; +} +//__________________________________________________________________________________________________ +OUString CompoundTypeDescriptionImpl::getName() + throw(::com::sun::star::uno::RuntimeException) +{ + return _aName; +} + +// XCompoundTypeDescription +//__________________________________________________________________________________________________ +Reference< XTypeDescription > CompoundTypeDescriptionImpl::getBaseType() + throw(::com::sun::star::uno::RuntimeException) +{ + if (!_xBaseTD.is() && _aBaseType.getLength()) + { + try + { + Reference< XTypeDescription > xBaseTD; + if (_xTDMgr->getByHierarchicalName( _aBaseType ) >>= xBaseTD) + { + MutexGuard aGuard( getMutex() ); + if (! _xBaseTD.is()) + _xBaseTD = xBaseTD; + return _xBaseTD; + } + } + catch (NoSuchElementException &) + { + } + // never try again, if no base td was found + _aBaseType = OUString(); + } + return _xBaseTD; +} +//__________________________________________________________________________________________________ + +namespace { + +class TypeParameter: public WeakImplHelper1< XTypeDescription > { +public: + explicit TypeParameter(OUString const & name): m_name(name) {} + + virtual TypeClass SAL_CALL getTypeClass() throw (RuntimeException) + { return TypeClass_UNKNOWN; } + + virtual OUString SAL_CALL getName() throw (RuntimeException) + { return m_name; } + +private: + OUString m_name; +}; + +} + +Sequence< Reference< XTypeDescription > > CompoundTypeDescriptionImpl::getMemberTypes() + throw(::com::sun::star::uno::RuntimeException) +{ + if (! _pMembers) + { + typereg::Reader aReader( + _aBytes.getConstArray(), _aBytes.getLength(), false, + TYPEREG_VERSION_1); + + sal_uInt16 nFields = aReader.getFieldCount(); + Sequence< Reference< XTypeDescription > > * pTempMembers = + new Sequence< Reference< XTypeDescription > >( nFields ); + Reference< XTypeDescription > * pMembers = pTempMembers->getArray(); + + while (nFields--) + { + if ((aReader.getFieldFlags(nFields) & RT_ACCESS_PARAMETERIZED_TYPE) + != 0) + { + pMembers[nFields] = new TypeParameter( + aReader.getFieldTypeName(nFields)); + } else { + try { + _xTDMgr->getByHierarchicalName( + aReader.getFieldTypeName(nFields).replace('/', '.')) + >>= pMembers[nFields]; + } catch (NoSuchElementException &) {} + OSL_ENSURE( + pMembers[nFields].is(), "### compound member unknown!"); + } + } + + ClearableMutexGuard aGuard( getMutex() ); + if (_pMembers) + { + aGuard.clear(); + delete pTempMembers; + } + else + { + _pMembers = pTempMembers; + } + } + + return *_pMembers; +} +//__________________________________________________________________________________________________ +Sequence< OUString > CompoundTypeDescriptionImpl::getMemberNames() + throw(::com::sun::star::uno::RuntimeException) +{ + if (! _pMemberNames) + { + typereg::Reader aReader( + _aBytes.getConstArray(), _aBytes.getLength(), false, + TYPEREG_VERSION_1); + + sal_uInt16 nFields = aReader.getFieldCount(); + Sequence< OUString > * pTempMemberNames = new Sequence< OUString >( nFields ); + OUString * pMemberNames = pTempMemberNames->getArray(); + + while (nFields--) + { + pMemberNames[nFields] = aReader.getFieldName( nFields ); + } + + ClearableMutexGuard aGuard( getMutex() ); + if (_pMemberNames) + { + aGuard.clear(); + delete pTempMemberNames; + } + else + { + _pMemberNames = pTempMemberNames; + } + } + return *_pMemberNames; +} + +} + + diff --git a/stoc/source/registry_tdprovider/tdconsts.cxx b/stoc/source/registry_tdprovider/tdconsts.cxx new file mode 100644 index 000000000000..fe98f010a3a9 --- /dev/null +++ b/stoc/source/registry_tdprovider/tdconsts.cxx @@ -0,0 +1,110 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include <osl/diagnose.h> +#include <rtl/ustrbuf.hxx> +#include "registry/reader.hxx" +#include "registry/version.h" +#include "base.hxx" + +namespace stoc_rdbtdp +{ + +//__________________________________________________________________________________________________ +// virtual +ConstantsTypeDescriptionImpl::~ConstantsTypeDescriptionImpl() +{ + delete _pMembers; + + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +// XTypeDescription +//__________________________________________________________________________________________________ +// virtual +TypeClass ConstantsTypeDescriptionImpl::getTypeClass() + throw( RuntimeException ) +{ + return TypeClass_CONSTANTS; +} +//__________________________________________________________________________________________________ +// virtual +OUString ConstantsTypeDescriptionImpl::getName() + throw( RuntimeException ) +{ + return _aName; +} + +// XConstantsTypeDescription +//__________________________________________________________________________________________________ +// virtual +Sequence< Reference< XConstantTypeDescription > > SAL_CALL +ConstantsTypeDescriptionImpl::getConstants() + throw ( RuntimeException ) +{ + if ( !_pMembers ) + { + typereg::Reader aReader( + _aBytes.getConstArray(), _aBytes.getLength(), false, + TYPEREG_VERSION_1); + + sal_uInt16 nFields = aReader.getFieldCount(); + Sequence< Reference< XConstantTypeDescription > > * pTempConsts + = new Sequence< Reference< XConstantTypeDescription > >( nFields ); + Reference< XConstantTypeDescription > * pConsts + = pTempConsts->getArray(); + + while ( nFields-- ) + { + rtl::OUStringBuffer aName( _aName ); + aName.appendAscii( "." ); + aName.append( aReader.getFieldName( nFields ) ); + + Any aValue( getRTValue( aReader.getFieldValue( nFields ) ) ); + + pConsts[ nFields ] + = new ConstantTypeDescriptionImpl( aName.makeStringAndClear(), + aValue ); + } + + ClearableMutexGuard aGuard( getMutex() ); + if ( _pMembers ) + { + aGuard.clear(); + delete pTempConsts; + } + else + { + _pMembers = pTempConsts; + } + } + return *_pMembers; +} + +} diff --git a/stoc/source/registry_tdprovider/tdef.cxx b/stoc/source/registry_tdprovider/tdef.cxx new file mode 100644 index 000000000000..91b182697122 --- /dev/null +++ b/stoc/source/registry_tdprovider/tdef.cxx @@ -0,0 +1,82 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include "base.hxx" + +namespace stoc_rdbtdp +{ +TypedefTypeDescriptionImpl::~TypedefTypeDescriptionImpl() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +// XTypeDescription +//__________________________________________________________________________________________________ +TypeClass TypedefTypeDescriptionImpl::getTypeClass() + throw(::com::sun::star::uno::RuntimeException) +{ + return TypeClass_TYPEDEF; +} +//__________________________________________________________________________________________________ +OUString TypedefTypeDescriptionImpl::getName() + throw(::com::sun::star::uno::RuntimeException) +{ + return _aName; +} + +// XIndirectTypeDescription +//__________________________________________________________________________________________________ +Reference< XTypeDescription > TypedefTypeDescriptionImpl::getReferencedType() + throw(::com::sun::star::uno::RuntimeException) +{ + if (!_xRefTD.is() && _aRefName.getLength()) + { + try + { + Reference< XTypeDescription > xRefTD; + if (_xTDMgr->getByHierarchicalName( _aRefName ) >>= xRefTD) + { + MutexGuard aGuard( getMutex() ); + if (! _xRefTD.is()) + _xRefTD = xRefTD; + return _xRefTD; + } + } + catch (NoSuchElementException &) + { + } + // never try again, if no base td was found + _aRefName = OUString(); + } + return _xRefTD; +} + +} + + diff --git a/stoc/source/registry_tdprovider/tdenum.cxx b/stoc/source/registry_tdprovider/tdenum.cxx new file mode 100644 index 000000000000..d6922ce4226a --- /dev/null +++ b/stoc/source/registry_tdprovider/tdenum.cxx @@ -0,0 +1,135 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include "base.hxx" + +#include "registry/reader.hxx" +#include "registry/version.h" + +namespace stoc_rdbtdp +{ + +//__________________________________________________________________________________________________ +EnumTypeDescriptionImpl::~EnumTypeDescriptionImpl() +{ + delete _pEnumNames; + delete _pEnumValues; + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +// XTypeDescription +//__________________________________________________________________________________________________ +TypeClass EnumTypeDescriptionImpl::getTypeClass() + throw(::com::sun::star::uno::RuntimeException) +{ + return TypeClass_ENUM; +} +//__________________________________________________________________________________________________ +OUString EnumTypeDescriptionImpl::getName() + throw(::com::sun::star::uno::RuntimeException) +{ + return _aName; +} + +// XEnumTypeDescription +//__________________________________________________________________________________________________ +sal_Int32 EnumTypeDescriptionImpl::getDefaultEnumValue() + throw(::com::sun::star::uno::RuntimeException) +{ + return _nDefaultValue; +} +//__________________________________________________________________________________________________ +Sequence< OUString > EnumTypeDescriptionImpl::getEnumNames() + throw(::com::sun::star::uno::RuntimeException) +{ + if (! _pEnumNames) + { + typereg::Reader aReader( + _aBytes.getConstArray(), _aBytes.getLength(), false, + TYPEREG_VERSION_1); + + sal_uInt16 nFields = aReader.getFieldCount(); + Sequence< OUString > * pTempEnumNames = new Sequence< OUString >( nFields ); + OUString * pEnumNames = pTempEnumNames->getArray(); + + while (nFields--) + { + pEnumNames[nFields] = aReader.getFieldName( nFields ); + } + + ClearableMutexGuard aGuard( getMutex() ); + if (_pEnumNames) + { + aGuard.clear(); + delete pTempEnumNames; + } + else + { + _pEnumNames = pTempEnumNames; + } + } + return *_pEnumNames; +} +//__________________________________________________________________________________________________ +Sequence< sal_Int32 > EnumTypeDescriptionImpl::getEnumValues() + throw(::com::sun::star::uno::RuntimeException) +{ + if (! _pEnumValues) + { + typereg::Reader aReader( + _aBytes.getConstArray(), _aBytes.getLength(), false, + TYPEREG_VERSION_1); + + sal_uInt16 nFields = aReader.getFieldCount(); + Sequence< sal_Int32 > * pTempEnumValues = new Sequence< sal_Int32 >( nFields ); + sal_Int32 * pEnumValues = pTempEnumValues->getArray(); + + while (nFields--) + { + pEnumValues[nFields] = getRTValueAsInt32( + aReader.getFieldValue( nFields ) ); + } + + ClearableMutexGuard aGuard( getMutex() ); + if (_pEnumValues) + { + aGuard.clear(); + delete pTempEnumValues; + } + else + { + _pEnumValues = pTempEnumValues; + } + } + return *_pEnumValues; +} + +} + + diff --git a/stoc/source/registry_tdprovider/tdiface.cxx b/stoc/source/registry_tdprovider/tdiface.cxx new file mode 100644 index 000000000000..abee4540773a --- /dev/null +++ b/stoc/source/registry_tdprovider/tdiface.cxx @@ -0,0 +1,585 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include <osl/diagnose.h> +#include <rtl/ustrbuf.hxx> +#include "registry/reader.hxx" +#include "registry/version.h" + +#include <com/sun/star/reflection/XInterfaceMemberTypeDescription.hpp> +#include <com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp> +#include <com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp> +#include <com/sun/star/reflection/XMethodParameter.hpp> +#include <com/sun/star/reflection/XParameter.hpp> +#include "com/sun/star/uno/RuntimeException.hpp" +#include "base.hxx" +#include "functiondescription.hxx" +#include "methoddescription.hxx" + +#include <memory> +#include <set> + +namespace stoc_rdbtdp +{ + +//================================================================================================== +class InterfaceMethodImpl : public WeakImplHelper1< XInterfaceMethodTypeDescription > +{ + stoc::registry_tdprovider::MethodDescription _desc; + + Reference< XHierarchicalNameAccess > _xTDMgr; + + OUString _aTypeName; + + OUString _aReturnType; + Reference< XTypeDescription > _xReturnTD; + + sal_Bool _bIsOneWay; + sal_Int32 _nPosition; + +public: + InterfaceMethodImpl( const Reference< XHierarchicalNameAccess > & xTDMgr, + const OUString & rTypeName, + const OUString & rMemberName, + const OUString & rReturnType, + const Sequence< sal_Int8 > & rBytes, + sal_uInt16 nMethodIndex, + sal_Bool bIsOneWay, + sal_Int32 nPosition ) + : _desc(xTDMgr, rMemberName, rBytes, nMethodIndex) + , _xTDMgr( xTDMgr ) + , _aTypeName( rTypeName ) + , _aReturnType( rReturnType ) + , _bIsOneWay( bIsOneWay ) + , _nPosition( nPosition ) + { + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + } + virtual ~InterfaceMethodImpl(); + + // XTypeDescription + virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException); + virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); + + // XInterfaceMemberTypeDescription + virtual OUString SAL_CALL getMemberName() throw(::com::sun::star::uno::RuntimeException) + { return _desc.getName(); } + virtual sal_Int32 SAL_CALL getPosition() throw(::com::sun::star::uno::RuntimeException); + + // XInterfaceMethodTypeDescription + virtual Reference< XTypeDescription > SAL_CALL getReturnType() throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isOneway() throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< Reference< XMethodParameter > > SAL_CALL getParameters() throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< Reference< XTypeDescription > > SAL_CALL getExceptions() throw(::com::sun::star::uno::RuntimeException); +}; +//__________________________________________________________________________________________________ +InterfaceMethodImpl::~InterfaceMethodImpl() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +// XTypeDescription +//__________________________________________________________________________________________________ +TypeClass InterfaceMethodImpl::getTypeClass() + throw(::com::sun::star::uno::RuntimeException) +{ + return TypeClass_INTERFACE_METHOD; +} +//__________________________________________________________________________________________________ +OUString InterfaceMethodImpl::getName() + throw(::com::sun::star::uno::RuntimeException) +{ + return _aTypeName; +} + +// XInterfaceMemberTypeDescription +//__________________________________________________________________________________________________ +sal_Int32 InterfaceMethodImpl::getPosition() + throw(::com::sun::star::uno::RuntimeException) +{ + return _nPosition; +} + +// XInterfaceMethodTypeDescription +//__________________________________________________________________________________________________ +Reference<XTypeDescription > InterfaceMethodImpl::getReturnType() + throw(::com::sun::star::uno::RuntimeException) +{ + if (!_xReturnTD.is() && _aReturnType.getLength()) + { + try + { + Reference< XTypeDescription > xReturnTD; + if (_xTDMgr->getByHierarchicalName( _aReturnType ) >>= xReturnTD) + { + MutexGuard aGuard( getMutex() ); + if (! _xReturnTD.is()) + _xReturnTD = xReturnTD; + return _xReturnTD; + } + } + catch (NoSuchElementException &) + { + } + // never try again, if no td was found + _aReturnType = OUString(); + } + return _xReturnTD; +} +//__________________________________________________________________________________________________ +sal_Bool InterfaceMethodImpl::isOneway() + throw(::com::sun::star::uno::RuntimeException) +{ + return _bIsOneWay; +} +//__________________________________________________________________________________________________ +Sequence<Reference<XMethodParameter > > InterfaceMethodImpl::getParameters() + throw(::com::sun::star::uno::RuntimeException) +{ + Sequence< Reference< XParameter > > s1(_desc.getParameters()); + Sequence< Reference< XMethodParameter > > s2(s1.getLength()); + for (sal_Int32 i = 0; i < s1.getLength(); ++i) { + s2[i] = s1[i].get(); + } + return s2; +} +//__________________________________________________________________________________________________ +Sequence<Reference<XTypeDescription > > InterfaceMethodImpl::getExceptions() + throw(::com::sun::star::uno::RuntimeException) +{ + Sequence< Reference< XCompoundTypeDescription > > s1( + _desc.getExceptions()); + Sequence< Reference< XTypeDescription > > s2(s1.getLength()); + for (sal_Int32 i = 0; i < s1.getLength(); ++i) { + s2[i] = s1[i].get(); + } + return s2; +} + + +//################################################################################################## +//################################################################################################## +//################################################################################################## + + +//================================================================================================== +class InterfaceAttributeImpl : public WeakImplHelper1< XInterfaceAttributeTypeDescription2 > +{ + Reference< XHierarchicalNameAccess > _xTDMgr; + + OUString _aTypeName; + OUString _aMemberName; + + OUString _aMemberTypeName; + Reference< XTypeDescription > _xMemberTD; + + sal_Bool _bReadOnly; + sal_Bool _bBound; + sal_Int32 _nPosition; + + std::auto_ptr< stoc::registry_tdprovider::FunctionDescription > _getter; + std::auto_ptr< stoc::registry_tdprovider::FunctionDescription > _setter; + +public: + InterfaceAttributeImpl( + const Reference< XHierarchicalNameAccess > & xTDMgr, + const OUString & rTypeName, + const OUString & rMemberName, + const OUString & rMemberTypeName, + sal_Bool bReadOnly, + sal_Bool bBound, + std::auto_ptr< stoc::registry_tdprovider::FunctionDescription > & + getter, + std::auto_ptr< stoc::registry_tdprovider::FunctionDescription > & + setter, + sal_Int32 nPosition ) + : _xTDMgr( xTDMgr ) + , _aTypeName( rTypeName ) + , _aMemberName( rMemberName ) + , _aMemberTypeName( rMemberTypeName ) + , _bReadOnly( bReadOnly ) + , _bBound( bBound ) + , _nPosition( nPosition ) + , _getter( getter ) + , _setter( setter ) + { + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + } + virtual ~InterfaceAttributeImpl(); + + // XTypeDescription + virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException); + virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); + + // XInterfaceMemberTypeDescription + virtual OUString SAL_CALL getMemberName() throw(::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getPosition() throw(::com::sun::star::uno::RuntimeException); + + // XInterfaceAttributeTypeDescription2 + virtual sal_Bool SAL_CALL isReadOnly() throw(::com::sun::star::uno::RuntimeException); + virtual Reference< XTypeDescription > SAL_CALL getType() throw(::com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isBound() throw (RuntimeException) + { return _bBound; } + + virtual Sequence< Reference< XCompoundTypeDescription > > SAL_CALL + getGetExceptions() throw (RuntimeException) + { + if (_getter.get() != 0) { + return _getter->getExceptions(); + } else { + return Sequence< Reference< XCompoundTypeDescription > >(); + } + } + + virtual Sequence< Reference< XCompoundTypeDescription > > SAL_CALL + getSetExceptions() throw (RuntimeException) + { + if (_setter.get() != 0) { + return _setter->getExceptions(); + } else { + return Sequence< Reference< XCompoundTypeDescription > >(); + } + } +}; + +InterfaceAttributeImpl::~InterfaceAttributeImpl() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} +// XTypeDescription +//__________________________________________________________________________________________________ +TypeClass InterfaceAttributeImpl::getTypeClass() + throw(::com::sun::star::uno::RuntimeException) +{ + return TypeClass_INTERFACE_ATTRIBUTE; +} +//__________________________________________________________________________________________________ +OUString InterfaceAttributeImpl::getName() + throw(::com::sun::star::uno::RuntimeException) +{ + return _aTypeName; +} + +// XInterfaceMemberTypeDescription +//__________________________________________________________________________________________________ +OUString InterfaceAttributeImpl::getMemberName() + throw(::com::sun::star::uno::RuntimeException) +{ + return _aMemberName; +} +//__________________________________________________________________________________________________ +sal_Int32 InterfaceAttributeImpl::getPosition() + throw(::com::sun::star::uno::RuntimeException) +{ + return _nPosition; +} + +// XInterfaceAttributeTypeDescription2 +//__________________________________________________________________________________________________ +sal_Bool InterfaceAttributeImpl::isReadOnly() + throw(::com::sun::star::uno::RuntimeException) +{ + return _bReadOnly; +} +//__________________________________________________________________________________________________ +Reference<XTypeDescription > InterfaceAttributeImpl::getType() + throw(::com::sun::star::uno::RuntimeException) +{ + if (!_xMemberTD.is() && _aMemberTypeName.getLength()) + { + try + { + Reference< XTypeDescription > xMemberTD; + if (_xTDMgr->getByHierarchicalName( _aMemberTypeName ) >>= xMemberTD) + { + MutexGuard aGuard( getMutex() ); + if (! _xMemberTD.is()) + _xMemberTD = xMemberTD; + return _xMemberTD; + } + } + catch (NoSuchElementException &) + { + } + // never try again, if no td was found + _aMemberTypeName = OUString(); + } + return _xMemberTD; +} + + +//################################################################################################## +//################################################################################################## +//################################################################################################## + +void InterfaceTypeDescriptionImpl::checkInterfaceType( + Reference< XTypeDescription > const & type) +{ + if (resolveTypedefs(type)->getTypeClass() != TypeClass_INTERFACE) { + throw RuntimeException( + OUString( + RTL_CONSTASCII_USTRINGPARAM( + "Interface base is not an interface type")), + static_cast< OWeakObject * >(this)); + } +} + +namespace { + +class BaseOffset { +public: + BaseOffset(Reference< XInterfaceTypeDescription2 > const & desc); + + sal_Int32 get() const { return offset; } + +private: + void calculateBases(Reference< XInterfaceTypeDescription2 > const & desc); + + void calculate(Reference< XInterfaceTypeDescription2 > const & desc); + + std::set< rtl::OUString > set; + sal_Int32 offset; +}; + +BaseOffset::BaseOffset(Reference< XInterfaceTypeDescription2 > const & desc) { + offset = 0; + calculateBases(desc); +} + +void BaseOffset::calculateBases( + Reference< XInterfaceTypeDescription2 > const & desc) +{ + Sequence< Reference < XTypeDescription > > bases(desc->getBaseTypes()); + for (sal_Int32 i = 0; i < bases.getLength(); ++i) { + calculate( + Reference< XInterfaceTypeDescription2 >( + resolveTypedefs(bases[i]), UNO_QUERY_THROW)); + } +} + +void BaseOffset::calculate(Reference< XInterfaceTypeDescription2 > const & desc) +{ + if (set.insert(desc->getName()).second) { + calculateBases(desc); + offset += desc->getMembers().getLength(); + } +} + +} + +//__________________________________________________________________________________________________ +InterfaceTypeDescriptionImpl::InterfaceTypeDescriptionImpl( + const Reference< XHierarchicalNameAccess > & xTDMgr, + const OUString & rName, const Sequence< OUString > & rBaseTypes, + const Sequence< OUString > & rOptionalBaseTypes, + const Sequence< sal_Int8 > & rBytes, bool published ) + : _xTDMgr( xTDMgr ) + , _aBytes( rBytes ) + , _aName( rName ) + , _aBaseTypes( rBaseTypes ) + , _aOptionalBaseTypes( rOptionalBaseTypes ) + , _membersInit( false ) + , _published( published ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); +} +//__________________________________________________________________________________________________ +InterfaceTypeDescriptionImpl::~InterfaceTypeDescriptionImpl() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +// XTypeDescription +//__________________________________________________________________________________________________ +TypeClass InterfaceTypeDescriptionImpl::getTypeClass() + throw(::com::sun::star::uno::RuntimeException) +{ + return TypeClass_INTERFACE; +} +//__________________________________________________________________________________________________ +OUString InterfaceTypeDescriptionImpl::getName() + throw(::com::sun::star::uno::RuntimeException) +{ + return _aName; +} + +// XInterfaceTypeDescription2 +//__________________________________________________________________________________________________ +Reference< XTypeDescription > InterfaceTypeDescriptionImpl::getBaseType() + throw(::com::sun::star::uno::RuntimeException) +{ + Sequence< Reference< XTypeDescription > > aBaseTypes(getBaseTypes()); + return aBaseTypes.getLength() >= 1 ? aBaseTypes[0] : 0; +} +//__________________________________________________________________________________________________ +Uik SAL_CALL InterfaceTypeDescriptionImpl::getUik() + throw(::com::sun::star::uno::RuntimeException) +{ + return Uik(); +} +//__________________________________________________________________________________________________ +Sequence< Reference< XInterfaceMemberTypeDescription > > InterfaceTypeDescriptionImpl::getMembers() + throw(::com::sun::star::uno::RuntimeException) +{ + osl::MutexGuard guard(getMutex()); + if (!_membersInit) { + _nBaseOffset = BaseOffset(this).get(); + typereg::Reader reader( + _aBytes.getConstArray(), _aBytes.getLength(), false, + TYPEREG_VERSION_1); + sal_Int32 count = 0; + sal_uInt16 methodCount = reader.getMethodCount(); + {for (sal_uInt16 i = 0; i < methodCount; ++i) { + RTMethodMode flags = reader.getMethodFlags(i); + if (flags != RT_MODE_ATTRIBUTE_GET + && flags != RT_MODE_ATTRIBUTE_SET) + { + ++count; + } + }} + sal_uInt16 fieldCount = reader.getFieldCount(); + count += fieldCount; + _members.realloc(count); + sal_Int32 index = 0; + {for (sal_uInt16 i = 0; i < fieldCount; ++i) { + rtl::OUString name(reader.getFieldName(i)); + rtl::OUStringBuffer typeName(getName()); + typeName.appendAscii(RTL_CONSTASCII_STRINGPARAM("::")); + typeName.append(name); + RTFieldAccess flags = reader.getFieldFlags(i); + std::auto_ptr< stoc::registry_tdprovider::FunctionDescription > + getter; + std::auto_ptr< stoc::registry_tdprovider::FunctionDescription > + setter; + for (sal_uInt16 j = 0; j < methodCount; ++j) { + if (reader.getMethodName(j) == name) { + switch (reader.getMethodFlags(j)) { + case RT_MODE_ATTRIBUTE_GET: + OSL_ASSERT(getter.get() == 0); + getter.reset( + new stoc::registry_tdprovider::FunctionDescription( + _xTDMgr, _aBytes, j)); + break; + + case RT_MODE_ATTRIBUTE_SET: + OSL_ASSERT(setter.get() == 0); + setter.reset( + new stoc::registry_tdprovider::FunctionDescription( + _xTDMgr, _aBytes, j)); + break; + + default: + OSL_ASSERT(false); + break; + } + } + } + _members[index] = new InterfaceAttributeImpl( + _xTDMgr, typeName.makeStringAndClear(), name, + reader.getFieldTypeName(i).replace('/', '.'), + (flags & RT_ACCESS_READONLY) != 0, + (flags & RT_ACCESS_BOUND) != 0, getter, setter, + _nBaseOffset + index); + ++index; + }} + {for (sal_uInt16 i = 0; i < methodCount; ++i) { + RTMethodMode flags = reader.getMethodFlags(i); + if (flags != RT_MODE_ATTRIBUTE_GET + && flags != RT_MODE_ATTRIBUTE_SET) + { + rtl::OUString name(reader.getMethodName(i)); + rtl::OUStringBuffer typeName(getName()); + typeName.appendAscii(RTL_CONSTASCII_STRINGPARAM("::")); + typeName.append(name); + _members[index] = new InterfaceMethodImpl( + _xTDMgr, typeName.makeStringAndClear(), name, + reader.getMethodReturnTypeName(i).replace('/', '.'), + _aBytes, i, flags == RT_MODE_ONEWAY, _nBaseOffset + index); + ++index; + } + }} + _membersInit = true; + } + return _members; +} + +Sequence< Reference< XTypeDescription > > +InterfaceTypeDescriptionImpl::getBaseTypes() throw (RuntimeException) { + MutexGuard guard(getMutex()); + if (_xBaseTDs.getLength() == 0 && _aBaseTypes.getLength() != 0) { + Sequence< Reference< XTypeDescription > > tds(_aBaseTypes.getLength()); + for (sal_Int32 i = 0; i < _aBaseTypes.getLength(); ++i) { + try { + _xTDMgr->getByHierarchicalName(_aBaseTypes[i]) >>= tds[i]; + } catch (NoSuchElementException & e) { + throw RuntimeException( + (OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.container.NoSuchElementException: ")) + + e.Message), + static_cast< OWeakObject * >(this)); + } + OSL_ASSERT(tds[i].is()); + checkInterfaceType(tds[i]); + } + _xBaseTDs = tds; + } + return _xBaseTDs; +} + +Sequence< Reference< XTypeDescription > > +InterfaceTypeDescriptionImpl::getOptionalBaseTypes() throw (RuntimeException) { + MutexGuard guard(getMutex()); + if (_xOptionalBaseTDs.getLength() == 0 + && _aOptionalBaseTypes.getLength() != 0) + { + Sequence< Reference< XTypeDescription > > tds( + _aOptionalBaseTypes.getLength()); + for (sal_Int32 i = 0; i < _aOptionalBaseTypes.getLength(); ++i) { + try { + _xTDMgr->getByHierarchicalName(_aOptionalBaseTypes[i]) + >>= tds[i]; + } catch (NoSuchElementException & e) { + throw RuntimeException( + (OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.container.NoSuchElementException: ")) + + e.Message), + static_cast< OWeakObject * >(this)); + } + OSL_ASSERT(tds[i].is()); + checkInterfaceType(tds[i]); + } + _xOptionalBaseTDs = tds; + } + return _xOptionalBaseTDs; +} + +} diff --git a/stoc/source/registry_tdprovider/tdmodule.cxx b/stoc/source/registry_tdprovider/tdmodule.cxx new file mode 100644 index 000000000000..50d0a2cfaca3 --- /dev/null +++ b/stoc/source/registry_tdprovider/tdmodule.cxx @@ -0,0 +1,126 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include <vector> +#include <osl/diagnose.h> +#include "base.hxx" + +namespace stoc_rdbtdp +{ + +//__________________________________________________________________________________________________ +// virtual +ModuleTypeDescriptionImpl::~ModuleTypeDescriptionImpl() +{ + delete _pMembers; + + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +// XTypeDescription +//__________________________________________________________________________________________________ +// virtual +TypeClass ModuleTypeDescriptionImpl::getTypeClass() + throw( RuntimeException ) +{ + return TypeClass_MODULE; +} +//__________________________________________________________________________________________________ +// virtual +OUString ModuleTypeDescriptionImpl::getName() + throw( RuntimeException ) +{ + return _aName; +} + +// XModuleTypeDescription +//__________________________________________________________________________________________________ +// virtual +Sequence< Reference< XTypeDescription > > SAL_CALL +ModuleTypeDescriptionImpl::getMembers() + throw ( RuntimeException ) +{ + if ( !_pMembers ) + { + Reference< XTypeDescriptionEnumeration > xEnum; + try + { + xEnum = _xTDMgr->createTypeDescriptionEnumeration( + _aName, + Sequence< TypeClass >(), + TypeDescriptionSearchDepth_ONE ); + } + catch ( NoSuchTypeNameException const & ) + { + } + catch ( InvalidTypeNameException const & ) + { + } + + OSL_ENSURE( xEnum.is(), + "ModuleTypeDescriptionImpl::getMembers - No enumeration!" ); + + std::vector< Reference< XTypeDescription > > aTDs; + while ( xEnum->hasMoreElements() ) + { + try + { + Reference< XTypeDescription > xTD( + xEnum->nextTypeDescription() ); + aTDs.push_back( xTD ); + } + catch ( NoSuchElementException const & ) + { + OSL_ENSURE( sal_False, + "ModuleTypeDescriptionImpl::getMembers - " + " Caught NoSuchElementException!" ); + } + } + + Sequence< Reference< XTypeDescription > > * pMembers + = new Sequence< Reference< XTypeDescription > >( aTDs.size() ); + for ( sal_Int32 n = 0; n < pMembers->getLength(); n++ ) + (*pMembers)[ n ] = aTDs[ n ]; + + ClearableMutexGuard aGuard( getMutex() ); + if ( _pMembers ) + { + aGuard.clear(); + delete pMembers; + } + else + { + _pMembers = pMembers; + } + } + return *_pMembers; +} + +} diff --git a/stoc/source/registry_tdprovider/tdprop.cxx b/stoc/source/registry_tdprovider/tdprop.cxx new file mode 100644 index 000000000000..b103b5f06192 --- /dev/null +++ b/stoc/source/registry_tdprovider/tdprop.cxx @@ -0,0 +1,68 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include <osl/diagnose.h> +#include "base.hxx" + +namespace stoc_rdbtdp +{ + +//__________________________________________________________________________________________________ +// virtual +ConstantTypeDescriptionImpl::~ConstantTypeDescriptionImpl() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +// XTypeDescription +//__________________________________________________________________________________________________ +// virtual +TypeClass ConstantTypeDescriptionImpl::getTypeClass() + throw( RuntimeException ) +{ + return TypeClass_CONSTANT; +} +//__________________________________________________________________________________________________ +// virtual +OUString ConstantTypeDescriptionImpl::getName() + throw( RuntimeException ) +{ + return _aName; +} + +// XConstantTypeDescription +//__________________________________________________________________________________________________ +// virtual +Any SAL_CALL ConstantTypeDescriptionImpl::getConstantValue() + throw( RuntimeException ) +{ + return _aValue; +} + +} diff --git a/stoc/source/registry_tdprovider/tdprovider.cxx b/stoc/source/registry_tdprovider/tdprovider.cxx new file mode 100644 index 000000000000..2cf26706993c --- /dev/null +++ b/stoc/source/registry_tdprovider/tdprovider.cxx @@ -0,0 +1,629 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include <osl/diagnose.h> +#include <osl/mutex.hxx> +#include <uno/dispatcher.h> +#include <uno/mapping.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/compbase4.hxx> +#include <cppuhelper/implbase2.hxx> +#include <cppuhelper/typeprovider.hxx> + +#include <cppuhelper/weakref.hxx> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/registry/XSimpleRegistry.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp> +#include "com/sun/star/uno/RuntimeException.hpp" + +#include "registry/reader.hxx" +#include "registry/version.h" +#include "base.hxx" +#include "rdbtdp_tdenumeration.hxx" +#include "structtypedescription.hxx" + +#define SERVICENAME "com.sun.star.reflection.TypeDescriptionProvider" +#define IMPLNAME "com.sun.star.comp.stoc.RegistryTypeDescriptionProvider" + +using namespace com::sun::star; +using namespace com::sun::star::beans; +using namespace com::sun::star::registry; + +extern rtl_StandardModuleCount g_moduleCount; + +namespace stoc_bootstrap +{ +uno::Sequence< OUString > rdbtdp_getSupportedServiceNames() +{ + static Sequence < OUString > *pNames = 0; + if( ! pNames ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( !pNames ) + { + static Sequence< OUString > seqNames(1); + seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME)); + pNames = &seqNames; + } + } + return *pNames; +} + +OUString rdbtdp_getImplementationName() +{ + static OUString *pImplName = 0; + if( ! pImplName ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( ! pImplName ) + { + static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) ); + pImplName = &implName; + } + } + return *pImplName; +} +} + +namespace stoc_rdbtdp +{ +struct MutexHolder +{ + Mutex _aComponentMutex; +}; +//================================================================================================== +class ProviderImpl + : public MutexHolder + , public WeakComponentImplHelper4< XServiceInfo, + XHierarchicalNameAccess, + XTypeDescriptionEnumerationAccess, + XInitialization > +{ + // XHierarchicalNameAccess + XTypeDescriptionEnumerationAccess wrapper + // first asking the tdmgr instance, then looking up locally + class TypeDescriptionManagerWrapper + : public ::cppu::WeakImplHelper2< + container::XHierarchicalNameAccess, + reflection::XTypeDescriptionEnumerationAccess> + { + com::sun::star::uno::Reference<container::XHierarchicalNameAccess> + m_xTDMgr; + com::sun::star::uno::Reference<container::XHierarchicalNameAccess> + m_xThisProvider; + public: + TypeDescriptionManagerWrapper( ProviderImpl * pProvider ) + : m_xTDMgr( pProvider->_xContext->getValueByName( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "/singletons/com.sun.star.reflection." + "theTypeDescriptionManager") ) ), + UNO_QUERY_THROW ), + m_xThisProvider( pProvider ) + {} + // XHierarchicalNameAccess + virtual Any SAL_CALL getByHierarchicalName( OUString const & name ) + throw (container::NoSuchElementException, RuntimeException); + virtual sal_Bool SAL_CALL hasByHierarchicalName( OUString const & name ) + throw (RuntimeException); + + // XTypeDescriptionEnumerationAccess + virtual uno::Reference< + reflection::XTypeDescriptionEnumeration > SAL_CALL + createTypeDescriptionEnumeration( + const ::rtl::OUString& moduleName, + const uno::Sequence< uno::TypeClass >& types, + reflection::TypeDescriptionSearchDepth depth ) + throw ( reflection::NoSuchTypeNameException, + reflection::InvalidTypeNameException, + uno::RuntimeException ); + }; + friend class TypeDescriptionManagerWrapper; + + com::sun::star::uno::Reference< XComponentContext > _xContext; + com::sun::star::uno::WeakReference<XHierarchicalNameAccess> _xTDMgr; + com::sun::star::uno::Reference< XHierarchicalNameAccess > getTDMgr() SAL_THROW( () ); + + RegistryKeyList _aBaseKeys; + +protected: + virtual void SAL_CALL disposing(); + +public: + ProviderImpl( const com::sun::star::uno::Reference< XComponentContext > & xContext ); + virtual ~ProviderImpl(); + + // XInitialization + virtual void SAL_CALL initialize( const Sequence< Any > & args ) throw (Exception, RuntimeException); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // XHierarchicalNameAccess + Any getByHierarchicalNameImpl( const OUString & rName ); + + virtual Any SAL_CALL getByHierarchicalName( const OUString & rName ) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasByHierarchicalName( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException); + + // XTypeDescriptionEnumerationAccess + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::reflection::XTypeDescriptionEnumeration > SAL_CALL + createTypeDescriptionEnumeration( + const ::rtl::OUString& moduleName, + const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::TypeClass >& types, + ::com::sun::star::reflection::TypeDescriptionSearchDepth depth ) + throw ( ::com::sun::star::reflection::NoSuchTypeNameException, + ::com::sun::star::reflection::InvalidTypeNameException, + ::com::sun::star::uno::RuntimeException ); +}; +//__________________________________________________________________________________________________ +ProviderImpl::ProviderImpl( const com::sun::star::uno::Reference< XComponentContext > & xContext ) + : WeakComponentImplHelper4< + XServiceInfo, XHierarchicalNameAccess, + XTypeDescriptionEnumerationAccess, XInitialization >( _aComponentMutex ) + , _xContext( xContext ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); +} +//__________________________________________________________________________________________________ +ProviderImpl::~ProviderImpl() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +//______________________________________________________________________________ +Any ProviderImpl::TypeDescriptionManagerWrapper::getByHierarchicalName( + OUString const & name ) throw (container::NoSuchElementException, + RuntimeException) +{ + try + { + // first try tdmgr: + return m_xTDMgr->getByHierarchicalName( name ); + } + catch (container::NoSuchElementException &) + { + // then lookup locally: + return m_xThisProvider->getByHierarchicalName( name ); + } +} + +//______________________________________________________________________________ +sal_Bool ProviderImpl::TypeDescriptionManagerWrapper::hasByHierarchicalName( + OUString const & name ) throw (RuntimeException) +{ + return m_xTDMgr->hasByHierarchicalName( name ) || m_xThisProvider->hasByHierarchicalName( name ); +} + +//______________________________________________________________________________ +uno::Reference< reflection::XTypeDescriptionEnumeration > SAL_CALL +ProviderImpl::TypeDescriptionManagerWrapper::createTypeDescriptionEnumeration( + const ::rtl::OUString& moduleName, + const uno::Sequence< uno::TypeClass >& types, + reflection::TypeDescriptionSearchDepth depth ) + throw ( reflection::NoSuchTypeNameException, + reflection::InvalidTypeNameException, + uno::RuntimeException ) +{ + try + { + // first try tdmgr: + uno::Reference< reflection::XTypeDescriptionEnumerationAccess > xTDEA( + m_xTDMgr, uno::UNO_QUERY_THROW ); + return + xTDEA->createTypeDescriptionEnumeration( moduleName, types, depth ); + } + catch (reflection::NoSuchTypeNameException &) + { + // then lookup locally: + uno::Reference< reflection::XTypeDescriptionEnumerationAccess > xTDEA( + m_xThisProvider, uno::UNO_QUERY_THROW ); + return + xTDEA->createTypeDescriptionEnumeration( moduleName, types, depth ); + } +} + +//__________________________________________________________________________________________________ +com::sun::star::uno::Reference< XHierarchicalNameAccess > ProviderImpl::getTDMgr() + SAL_THROW( () ) +{ + // harden weak reference: + com::sun::star::uno::Reference<container::XHierarchicalNameAccess> xTDMgr( + _xTDMgr ); + if (! xTDMgr.is()) + { + xTDMgr.set( new TypeDescriptionManagerWrapper(this) ); + { + MutexGuard guard( _aComponentMutex ); + _xTDMgr = xTDMgr; + } + } + return xTDMgr; +} + +//__________________________________________________________________________________________________ +void ProviderImpl::disposing() +{ + _xContext.clear(); + + for ( RegistryKeyList::const_iterator iPos( _aBaseKeys.begin() ); + iPos != _aBaseKeys.end(); ++iPos ) + { + (*iPos)->closeKey(); + } + _aBaseKeys.clear(); +} + +// XInitialization +//__________________________________________________________________________________________________ +void ProviderImpl::initialize( + const Sequence< Any > & args ) + throw (Exception, RuntimeException) +{ + // registries to read from + Any const * pRegistries = args.getConstArray(); + for ( sal_Int32 nPos = 0; nPos < args.getLength(); ++nPos ) + { + com::sun::star::uno::Reference< XSimpleRegistry > xRegistry( pRegistries[ nPos ], UNO_QUERY ); + if (xRegistry.is() && xRegistry->isValid()) + { + com::sun::star::uno::Reference< XRegistryKey > xKey( xRegistry->getRootKey()->openKey( + OUString( RTL_CONSTASCII_USTRINGPARAM("/UCR") ) ) ); + if (xKey.is() && xKey->isValid()) + { + _aBaseKeys.push_back( xKey ); + } + } + } +} + +// XServiceInfo +//__________________________________________________________________________________________________ +OUString ProviderImpl::getImplementationName() + throw(::com::sun::star::uno::RuntimeException) +{ + return stoc_bootstrap::rdbtdp_getImplementationName(); +} +//__________________________________________________________________________________________________ +sal_Bool ProviderImpl::supportsService( const OUString & rServiceName ) + throw(::com::sun::star::uno::RuntimeException) +{ + const Sequence< OUString > & rSNL = getSupportedServiceNames(); + const OUString * pArray = rSNL.getConstArray(); + for ( sal_Int32 nPos = rSNL.getLength(); nPos--; ) + { + if (pArray[nPos] == rServiceName) + return sal_True; + } + return sal_False; +} +//__________________________________________________________________________________________________ +Sequence< OUString > ProviderImpl::getSupportedServiceNames() + throw(::com::sun::star::uno::RuntimeException) +{ + return stoc_bootstrap::rdbtdp_getSupportedServiceNames(); +} + +// XHierarchicalNameAccess +//__________________________________________________________________________________________________ +Any ProviderImpl::getByHierarchicalNameImpl( const OUString & rName ) +{ + Any aRet; + + // read from registry + OUString aKey( rName.replace( '.', '/' ) ); + for ( RegistryKeyList::const_iterator iPos( _aBaseKeys.begin() ); + !aRet.hasValue() && iPos != _aBaseKeys.end(); ++iPos ) + { + try + { + com::sun::star::uno::Reference< XRegistryKey > xBaseKey( *iPos ); + com::sun::star::uno::Reference< XRegistryKey > xKey( xBaseKey->openKey( aKey ) ); + if (xKey.is()) + { + // closes key in it's dtor (which is + // called even in case of exceptions). + RegistryKeyCloser aCloser( xKey ); + + if ( xKey->isValid() ) + { + if (xKey->getValueType() == RegistryValueType_BINARY) + { + Sequence< sal_Int8 > aBytes( xKey->getBinaryValue() ); + com::sun::star::uno::Reference< XTypeDescription > xTD( + createTypeDescription( aBytes, + getTDMgr(), + true ) ); + if ( xTD.is() ) + aRet <<= xTD; + } + } + } + else // might be a constant + { + sal_Int32 nIndex = aKey.lastIndexOf( '/' ); + if (nIndex > 0) + { + // open module + com::sun::star::uno::Reference< XRegistryKey > xKey2( xBaseKey->openKey( aKey.copy( 0, nIndex ) ) ); + if (xKey2.is()) + { + // closes key in it's dtor (which is + // called even in case of exceptions). + RegistryKeyCloser aCloser( xKey2 ); + + if ( xKey2->isValid() ) + { + if (xKey2->getValueType() == RegistryValueType_BINARY) + { + Sequence< sal_Int8 > aBytes( xKey2->getBinaryValue() ); + typereg::Reader aReader( + aBytes.getConstArray(), aBytes.getLength(), + false, TYPEREG_VERSION_1); + + if (aReader.getTypeClass() == RT_TYPE_MODULE || + aReader.getTypeClass() == RT_TYPE_CONSTANTS || + aReader.getTypeClass() == RT_TYPE_ENUM) + { + OUString aFieldName( aKey.copy( nIndex+1, aKey.getLength() - nIndex -1 ) ); + sal_Int16 nPos = aReader.getFieldCount(); + while (nPos--) + { + if (aFieldName.equals( + aReader.getFieldName(nPos))) + break; + } + if (nPos >= 0) + aRet = getRTValue( + aReader.getFieldValue(nPos)); + } + } + } + } + } + } + } + catch ( InvalidRegistryException const & ) + { + OSL_ENSURE( sal_False, + "ProviderImpl::getByHierarchicalName " + "- Caught InvalidRegistryException!" ); + + // openKey, closeKey, getValueType, getBinaryValue, isValid + + // Don't stop iteration in this case. + } + catch ( NoSuchElementException const & ) + { + } + } + return aRet; +} + +Any SAL_CALL ProviderImpl::getByHierarchicalName( const OUString & rName ) + throw(::com::sun::star::uno::RuntimeException, com::sun::star::container::NoSuchElementException) +{ + Any aRet( getByHierarchicalNameImpl( rName ) ); + + if ( !aRet.hasValue() ) + throw NoSuchElementException( + rName, static_cast< cppu::OWeakObject * >( this ) ); + + return aRet; +} + +//__________________________________________________________________________________________________ +sal_Bool ProviderImpl::hasByHierarchicalName( const OUString & rName ) + throw(::com::sun::star::uno::RuntimeException) +{ + return getByHierarchicalNameImpl( rName ).hasValue(); +} + +// XTypeDescriptionEnumerationAccess +//__________________________________________________________________________________________________ +// virtual +com::sun::star::uno::Reference< XTypeDescriptionEnumeration > SAL_CALL +ProviderImpl::createTypeDescriptionEnumeration( + const OUString & moduleName, + const Sequence< TypeClass > & types, + TypeDescriptionSearchDepth depth ) + throw ( NoSuchTypeNameException, + InvalidTypeNameException, + RuntimeException ) +{ + return com::sun::star::uno::Reference< XTypeDescriptionEnumeration >( + TypeDescriptionEnumerationImpl::createInstance( getTDMgr(), + moduleName, + types, + depth, + _aBaseKeys ).get() ); +} + +//__________________________________________________________________________________________________ +// global helper function + +com::sun::star::uno::Reference< XTypeDescription > resolveTypedefs( + com::sun::star::uno::Reference< XTypeDescription > const & type) +{ + com::sun::star::uno::Reference< XTypeDescription > resolved(type); + while (resolved->getTypeClass() == TypeClass_TYPEDEF) { + resolved = com::sun::star::uno::Reference< XIndirectTypeDescription >( + resolved, UNO_QUERY_THROW)->getReferencedType(); + } + return resolved; +} + +com::sun::star::uno::Reference< XTypeDescription > createTypeDescription( + const Sequence< sal_Int8 > & rData, + const com::sun::star::uno::Reference< XHierarchicalNameAccess > & xNameAccess, + bool bReturnEmptyRefForUnknownType ) +{ + typereg::Reader aReader( + rData.getConstArray(), rData.getLength(), false, TYPEREG_VERSION_1); + + OUString aName( aReader.getTypeName().replace( '/', '.' ) ); + + switch (aReader.getTypeClass()) + { + case RT_TYPE_INTERFACE: + { + sal_uInt16 n = aReader.getSuperTypeCount(); + com::sun::star::uno::Sequence< rtl::OUString > aBaseTypeNames(n); + {for (sal_uInt16 i = 0; i < n; ++i) { + aBaseTypeNames[i] = aReader.getSuperTypeName(i).replace( + '/', '.'); + }} + sal_uInt16 n2 = aReader.getReferenceCount(); + com::sun::star::uno::Sequence< rtl::OUString > + aOptionalBaseTypeNames(n2); + {for (sal_uInt16 i = 0; i < n2; ++i) { + OSL_ASSERT( + aReader.getReferenceSort(i) == RT_REF_SUPPORTS + && aReader.getReferenceFlags(i) == RT_ACCESS_OPTIONAL); + aOptionalBaseTypeNames[i] = aReader.getReferenceTypeName(i); + }} + return com::sun::star::uno::Reference< XTypeDescription >( + new InterfaceTypeDescriptionImpl( xNameAccess, + aName, + aBaseTypeNames, + aOptionalBaseTypeNames, + rData, + aReader.isPublished() ) ); + } + + case RT_TYPE_MODULE: + { + com::sun::star::uno::Reference< + XTypeDescriptionEnumerationAccess > xTDEA( + xNameAccess, UNO_QUERY ); + + OSL_ENSURE( xTDEA.is(), + "No XTypeDescriptionEnumerationAccess!" ); + + return com::sun::star::uno::Reference< XTypeDescription >( + new ModuleTypeDescriptionImpl( xTDEA, aName ) ); + } + + case RT_TYPE_STRUCT: + { + rtl::OUString superTypeName; + if (aReader.getSuperTypeCount() == 1) { + superTypeName = aReader.getSuperTypeName(0).replace( + '/', '.'); + } + return com::sun::star::uno::Reference< XTypeDescription >( + new stoc::registry_tdprovider::StructTypeDescription( + xNameAccess, aName, superTypeName, rData, + aReader.isPublished())); + } + + case RT_TYPE_ENUM: + return com::sun::star::uno::Reference< XTypeDescription >( + new EnumTypeDescriptionImpl( xNameAccess, + aName, + getRTValueAsInt32( + aReader.getFieldValue( 0 ) ), + rData, aReader.isPublished() ) ); + + case RT_TYPE_EXCEPTION: + { + rtl::OUString superTypeName; + if (aReader.getSuperTypeCount() == 1) { + superTypeName = aReader.getSuperTypeName(0).replace( + '/', '.'); + } + return com::sun::star::uno::Reference< XTypeDescription >( + new CompoundTypeDescriptionImpl( + xNameAccess, TypeClass_EXCEPTION, aName, superTypeName, + rData, aReader.isPublished())); + } + + case RT_TYPE_TYPEDEF: + return com::sun::star::uno::Reference< XTypeDescription >( + new TypedefTypeDescriptionImpl( xNameAccess, + aName, + aReader.getSuperTypeName(0) + .replace( '/', '.' ), + aReader.isPublished() ) ); + case RT_TYPE_SERVICE: + return com::sun::star::uno::Reference< XTypeDescription >( + new ServiceTypeDescriptionImpl( + xNameAccess, aName, rData, aReader.isPublished() ) ); + + case RT_TYPE_CONSTANTS: + return com::sun::star::uno::Reference< XTypeDescription >( + new ConstantsTypeDescriptionImpl( + aName, rData, aReader.isPublished() ) ); + + case RT_TYPE_SINGLETON: + return com::sun::star::uno::Reference< XTypeDescription >( + new SingletonTypeDescriptionImpl( xNameAccess, + aName, + aReader.getSuperTypeName(0) + .replace( '/', '.' ), + aReader.isPublished() ) ); + case RT_TYPE_INVALID: + case RT_TYPE_OBJECT: // deprecated and not used + case RT_TYPE_UNION: // deprecated and not used + OSL_ENSURE( sal_False, "createTypeDescription - Unsupported Type!" ); + break; + + default: + OSL_ENSURE( sal_False, "createTypeDescription - Unknown Type!" ); + break; + } + + // Unknown type. + + if ( bReturnEmptyRefForUnknownType ) + return com::sun::star::uno::Reference< XTypeDescription >(); + + return com::sun::star::uno::Reference< XTypeDescription >( + new TypeDescriptionImpl( TypeClass_UNKNOWN, aName ) ); +} + +} + +namespace stoc_bootstrap +{ +//================================================================================================== +com::sun::star::uno::Reference< XInterface > SAL_CALL ProviderImpl_create( + com::sun::star::uno::Reference< XComponentContext > const & xContext ) + throw(::com::sun::star::uno::Exception) +{ + return com::sun::star::uno::Reference< XInterface >( *new stoc_rdbtdp::ProviderImpl( xContext ) ); +} +} diff --git a/stoc/source/registry_tdprovider/tdservice.cxx b/stoc/source/registry_tdprovider/tdservice.cxx new file mode 100644 index 000000000000..b8a1de58b1aa --- /dev/null +++ b/stoc/source/registry_tdprovider/tdservice.cxx @@ -0,0 +1,565 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include <osl/diagnose.h> +#include <rtl/ustrbuf.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include "com/sun/star/uno/RuntimeException.hpp" + +#include "registry/reader.hxx" +#include "registry/version.h" +#include "base.hxx" +#include "methoddescription.hxx" + +#include <memory> + +using namespace com::sun::star; + +namespace { + +class Constructor: + public cppu::WeakImplHelper1< XServiceConstructorDescription > +{ +public: + Constructor( + Reference< XHierarchicalNameAccess > const & manager, + rtl::OUString const & name, Sequence< sal_Int8 > const & bytes, + sal_uInt16 index): + m_desc(manager, name, bytes, index) {} + + virtual ~Constructor() {} + + virtual sal_Bool SAL_CALL isDefaultConstructor() throw (RuntimeException) + { return m_desc.getName().getLength() == 0; } + + virtual rtl::OUString SAL_CALL getName() throw (RuntimeException) + { return m_desc.getName(); } + + virtual Sequence< Reference< XParameter > > SAL_CALL getParameters() + throw (RuntimeException) + { return m_desc.getParameters(); } + + virtual Sequence< Reference<XCompoundTypeDescription > > SAL_CALL + getExceptions() throw (RuntimeException) + { return m_desc.getExceptions(); } + +private: + Constructor(Constructor &); // not implemented + void operator =(Constructor); // not implemented + + stoc::registry_tdprovider::MethodDescription m_desc; +}; + +} + +namespace stoc_rdbtdp +{ + +//================================================================================================== +// +// class PropertyTypeDescriptionImpl +// +//================================================================================================== +class PropertyTypeDescriptionImpl : public WeakImplHelper1< XPropertyTypeDescription > +{ + OUString _aName; + Reference< XTypeDescription > _xTD; + sal_Int16 _nFlags; + +public: + PropertyTypeDescriptionImpl( const OUString & rName, + const Reference< XTypeDescription > & xTD, + sal_Int16 nFlags ) + : _aName( rName ), _xTD( xTD ), _nFlags( nFlags ) + { + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + } + virtual ~PropertyTypeDescriptionImpl(); + + // XTypeDescription + virtual TypeClass SAL_CALL getTypeClass() + throw( RuntimeException ); + virtual OUString SAL_CALL getName() + throw( RuntimeException ); + + // XPropertyTypeDescription + virtual sal_Int16 SAL_CALL getPropertyFlags() + throw ( RuntimeException ); + virtual Reference< XTypeDescription > SAL_CALL getPropertyTypeDescription() + throw ( RuntimeException ); +}; + +//__________________________________________________________________________________________________ +// virtual +PropertyTypeDescriptionImpl::~PropertyTypeDescriptionImpl() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +// XTypeDescription +//__________________________________________________________________________________________________ +// virtual +TypeClass PropertyTypeDescriptionImpl::getTypeClass() + throw ( RuntimeException ) +{ + return TypeClass_PROPERTY; +} +//__________________________________________________________________________________________________ +// virtual +OUString PropertyTypeDescriptionImpl::getName() + throw ( RuntimeException ) +{ + return _aName; +} + +// XPropertyTypeDescription +//__________________________________________________________________________________________________ +// virtual +sal_Int16 SAL_CALL PropertyTypeDescriptionImpl::getPropertyFlags() + throw ( RuntimeException ) +{ + return _nFlags; +} + +//__________________________________________________________________________________________________ +// virtual +Reference< XTypeDescription > SAL_CALL +PropertyTypeDescriptionImpl::getPropertyTypeDescription() + throw ( RuntimeException ) +{ + return _xTD; +} + +//================================================================================================== +// +// ServiceTypeDescriptionImpl implementation +// +//================================================================================================== + +//__________________________________________________________________________________________________ +// virtual +ServiceTypeDescriptionImpl::~ServiceTypeDescriptionImpl() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +// XTypeDescription +//__________________________________________________________________________________________________ +// virtual +TypeClass ServiceTypeDescriptionImpl::getTypeClass() + throw(::com::sun::star::uno::RuntimeException) +{ + return TypeClass_SERVICE; +} +//__________________________________________________________________________________________________ +// virtual +OUString ServiceTypeDescriptionImpl::getName() + throw(::com::sun::star::uno::RuntimeException) +{ + return _aName; +} + +// XServiceTypeDescription +//__________________________________________________________________________________________________ +// virtual +Sequence< Reference< XServiceTypeDescription > > SAL_CALL +ServiceTypeDescriptionImpl::getMandatoryServices() + throw ( RuntimeException ) +{ + getReferences(); + return _aMandatoryServices; +} + +//__________________________________________________________________________________________________ +// virtual +Sequence< Reference< XServiceTypeDescription > > SAL_CALL +ServiceTypeDescriptionImpl::getOptionalServices() + throw ( RuntimeException ) +{ + getReferences(); + return _aOptionalServices; +} + +//__________________________________________________________________________________________________ +// virtual +Sequence< Reference< XInterfaceTypeDescription > > SAL_CALL +ServiceTypeDescriptionImpl::getMandatoryInterfaces() + throw ( RuntimeException ) +{ + getReferences(); + return _aMandatoryInterfaces; +} + +//__________________________________________________________________________________________________ +// virtual +Sequence< Reference< XInterfaceTypeDescription > > SAL_CALL +ServiceTypeDescriptionImpl::getOptionalInterfaces() + throw ( RuntimeException ) +{ + getReferences(); + return _aOptionalInterfaces; +} + +//__________________________________________________________________________________________________ +// virtual +Sequence< Reference< XPropertyTypeDescription > > SAL_CALL +ServiceTypeDescriptionImpl::getProperties() + throw ( RuntimeException ) +{ + { + MutexGuard guard(getMutex()); + if (_pProps.get() != 0) { + return *_pProps; + } + } + + typereg::Reader aReader( + _aBytes.getConstArray(), _aBytes.getLength(), false, TYPEREG_VERSION_1); + + sal_uInt16 nFields = (sal_uInt16)aReader.getFieldCount(); + std::auto_ptr< Sequence< Reference< XPropertyTypeDescription > > > + pTempProps( + new Sequence< Reference< XPropertyTypeDescription > >(nFields)); + Reference< XPropertyTypeDescription > * pProps = pTempProps->getArray(); + + while ( nFields-- ) + { + // name + OUStringBuffer aName( _aName ); + aName.appendAscii( "." ); + aName.append( aReader.getFieldName( nFields ) ); + + // type description + Reference< XTypeDescription > xTD; + try + { + _xTDMgr->getByHierarchicalName( + aReader.getFieldTypeName( nFields ).replace( '/', '.' ) ) + >>= xTD; + } + catch ( NoSuchElementException const & ) + { + } + OSL_ENSURE( xTD.is(), "### no type description for property!" ); + + // flags + RTFieldAccess nFlags = aReader.getFieldFlags( nFields ); + + sal_Int16 nAttribs = 0; + if ( nFlags & RT_ACCESS_READONLY ) + nAttribs |= beans::PropertyAttribute::READONLY; + if ( nFlags & RT_ACCESS_OPTIONAL ) + nAttribs |= beans::PropertyAttribute::OPTIONAL; + if ( nFlags & RT_ACCESS_MAYBEVOID ) + nAttribs |= beans::PropertyAttribute::MAYBEVOID; + if ( nFlags & RT_ACCESS_BOUND ) + nAttribs |= beans::PropertyAttribute::BOUND; + if ( nFlags & RT_ACCESS_CONSTRAINED ) + nAttribs |= beans::PropertyAttribute::CONSTRAINED; + if ( nFlags & RT_ACCESS_TRANSIENT ) + nAttribs |= beans::PropertyAttribute::TRANSIENT; + if ( nFlags & RT_ACCESS_MAYBEAMBIGUOUS ) + nAttribs |= beans::PropertyAttribute::MAYBEAMBIGUOUS; + if ( nFlags & RT_ACCESS_MAYBEDEFAULT ) + nAttribs |= beans::PropertyAttribute::MAYBEDEFAULT; + if ( nFlags & RT_ACCESS_REMOVEABLE ) + nAttribs |= beans::PropertyAttribute::REMOVEABLE; + + OSL_ENSURE( !(nFlags & RT_ACCESS_PROPERTY), + "### RT_ACCESS_PROPERTY is unexpected here!" ); + OSL_ENSURE( !(nFlags & RT_ACCESS_ATTRIBUTE), + "### RT_ACCESS_ATTRIBUTE is unexpected here!" ); + OSL_ENSURE( !(nFlags & RT_ACCESS_CONST), + "### RT_ACCESS_CONST is unexpected here!" ); + // always set, unless RT_ACCESS_READONLY is set. + //OSL_ENSURE( !(nFlags & RT_ACCESS_READWRITE), + // "### RT_ACCESS_READWRITE is unexpected here" ); + OSL_ENSURE( !(nFlags & RT_ACCESS_DEFAULT), + "### RT_ACCESS_DEAFAULT is unexpected here" ); + + pProps[ nFields ] + = new PropertyTypeDescriptionImpl( aName.makeStringAndClear(), + xTD, + nAttribs ); + } + + MutexGuard guard(getMutex()); + if (_pProps.get() == 0) { + _pProps = pTempProps; + } + return *_pProps; +} + +sal_Bool ServiceTypeDescriptionImpl::isSingleInterfaceBased() + throw (RuntimeException) +{ + getReferences(); + return _xInterfaceTD.is(); +} + +Reference< XTypeDescription > ServiceTypeDescriptionImpl::getInterface() + throw (RuntimeException) +{ + getReferences(); + return _xInterfaceTD; +} + +Sequence< Reference< XServiceConstructorDescription > > +ServiceTypeDescriptionImpl::getConstructors() throw (RuntimeException) { + MutexGuard guard(getMutex()); + if (_pCtors.get() == 0) { + typereg::Reader reader( + _aBytes.getConstArray(), _aBytes.getLength(), false, + TYPEREG_VERSION_1); + sal_uInt16 ctorCount = reader.getMethodCount(); + std::auto_ptr< Sequence< Reference< XServiceConstructorDescription > > > + ctors( + new Sequence< Reference< XServiceConstructorDescription > >( + ctorCount)); + for (sal_uInt16 i = 0; i < ctorCount; ++i) { + rtl::OUString name(reader.getMethodName(i)); + if (reader.getMethodFlags(i) != RT_MODE_TWOWAY + || (!reader.getMethodReturnTypeName(i).equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("void"))) + || (name.getLength() == 0 + && (ctorCount != 1 || reader.getMethodParameterCount(i) != 0 + || reader.getMethodExceptionCount(i) != 0))) + { + throw RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "Service has bad constructors")), + static_cast< OWeakObject * >(this)); + } + (*ctors)[i] = new Constructor( + _xTDMgr, reader.getMethodName(i), _aBytes, i); + } + _pCtors = ctors; + } + return *_pCtors; +} + +//__________________________________________________________________________________________________ +void ServiceTypeDescriptionImpl::getReferences() + throw ( RuntimeException ) +{ + { + MutexGuard guard(getMutex()); + if (_bInitReferences) { + return; + } + } + typereg::Reader aReader( + _aBytes.getConstArray(), _aBytes.getLength(), false, TYPEREG_VERSION_1); + sal_uInt16 superTypes = aReader.getSuperTypeCount(); + if (superTypes > 1) { + throw RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "Service has more than one supertype")), + static_cast< OWeakObject * >(this)); + } + if (superTypes == 1) { + OUString aBaseName( aReader.getSuperTypeName(0).replace( '/', '.' ) ); + if ( aReader.getReferenceCount() != 0 + || aReader.getFieldCount() != 0 ) + throw RuntimeException( + OUString( + RTL_CONSTASCII_USTRINGPARAM( + "Service is single-interface--based but also has" + " references and/or properties" ) ), + static_cast< OWeakObject * >( this ) ); + Reference< XTypeDescription > ifc; + try + { + _xTDMgr->getByHierarchicalName( aBaseName ) >>= ifc; + } + catch ( NoSuchElementException const & e ) + { + throw RuntimeException( + OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.container.NoSuchElementException: " ) ) + + e.Message, + static_cast< OWeakObject * >( this ) ); + } + OSL_ASSERT(ifc.is()); + if (resolveTypedefs(ifc)->getTypeClass() != TypeClass_INTERFACE) { + throw RuntimeException( + OUString( + RTL_CONSTASCII_USTRINGPARAM( + "Single-interface--based service is not based on" + " interface type" ) ), + static_cast< OWeakObject * >( this ) ); + } + MutexGuard guard(getMutex()); + if (!_bInitReferences) { + _xInterfaceTD = ifc; + _bInitReferences = true; + } + } + else + { + sal_uInt16 nRefs = aReader.getReferenceCount(); + Sequence< Reference< XServiceTypeDescription > > aMandatoryServices( + nRefs); + Sequence< Reference< XServiceTypeDescription > > aOptionalServices( + nRefs); + Sequence< Reference< XInterfaceTypeDescription > > aMandatoryInterfaces( + nRefs); + Sequence< Reference< XInterfaceTypeDescription > > aOptionalInterfaces( + nRefs); + sal_uInt32 nMS = 0; + sal_uInt32 nOS = 0; + sal_uInt32 nMI = 0; + sal_uInt32 nOI = 0; + + for ( sal_uInt16 nPos = 0; nPos < nRefs; ++nPos ) + { + RTReferenceType eType = aReader.getReferenceSort( nPos ); + switch ( eType ) + { + case RT_REF_EXPORTS: // service + { + uno::Any aTypeDesc; + try + { + aTypeDesc = _xTDMgr->getByHierarchicalName( + aReader.getReferenceTypeName( nPos ).replace( + '/', '.' ) ); + } + catch ( NoSuchElementException const & e ) + { + throw RuntimeException( + OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.container." + "NoSuchElementException: " ) ) + + e.Message, + static_cast< OWeakObject * >( this ) ); + } + + RTFieldAccess nAccess = aReader.getReferenceFlags( nPos ); + if ( nAccess & RT_ACCESS_OPTIONAL ) + { + // optional service + if ( !( aTypeDesc >>= aOptionalServices[ nOS ] ) ) + throw RuntimeException( + OUString( + RTL_CONSTASCII_USTRINGPARAM( + "Service 'export' is not a service" ) ), + static_cast< OWeakObject * >( this ) ); + nOS++; + } + else + { + // mandatory service + if ( !( aTypeDesc >>= aMandatoryServices[ nMS ] ) ) + throw RuntimeException( + OUString( + RTL_CONSTASCII_USTRINGPARAM( + "Service 'export' is not a service" ) ), + static_cast< OWeakObject * >( this ) ); + nMS++; + } + break; + } + case RT_REF_SUPPORTS: // interface + { + uno::Any aTypeDesc; + try + { + aTypeDesc = _xTDMgr->getByHierarchicalName( + aReader.getReferenceTypeName( nPos ).replace( + '/', '.' ) ); + } + catch ( NoSuchElementException const & e ) + { + throw RuntimeException( + OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.container." + "NoSuchElementException: " ) ) + + e.Message, + static_cast< OWeakObject * >( this ) ); + } + + RTFieldAccess nAccess = aReader.getReferenceFlags( nPos ); + if ( nAccess & RT_ACCESS_OPTIONAL ) + { + // optional interface + if ( !( aTypeDesc >>= aOptionalInterfaces[ nOI ] ) ) + throw RuntimeException( + OUString( + RTL_CONSTASCII_USTRINGPARAM( + "Service 'supports' is not an" + " interface" ) ), + static_cast< OWeakObject * >( this ) ); + nOI++; + } + else + { + // mandatory interface + if ( !( aTypeDesc >>= aMandatoryInterfaces[ nMI ] ) ) + throw RuntimeException( + OUString( + RTL_CONSTASCII_USTRINGPARAM( + "Service 'supports' is not an" + " interface" ) ), + static_cast< OWeakObject * >( this ) ); + nMI++; + } + break; + } + case RT_REF_OBSERVES: + case RT_REF_NEEDS: + break; + default: + OSL_ENSURE( sal_False, "### unsupported reference type!" ); + break; + } + } + aMandatoryServices.realloc( nMS ); + aOptionalServices.realloc( nOS ); + aMandatoryInterfaces.realloc( nMI ); + aOptionalInterfaces.realloc( nOI ); + + MutexGuard guard(getMutex()); + if (!_bInitReferences) { + _aMandatoryServices = aMandatoryServices; + _aOptionalServices = aOptionalServices; + _aMandatoryInterfaces = aMandatoryInterfaces; + _aOptionalInterfaces = aOptionalInterfaces; + _bInitReferences = true; + } + } +} + + +} diff --git a/stoc/source/registry_tdprovider/tdsingleton.cxx b/stoc/source/registry_tdprovider/tdsingleton.cxx new file mode 100644 index 000000000000..ef38dacb657e --- /dev/null +++ b/stoc/source/registry_tdprovider/tdsingleton.cxx @@ -0,0 +1,132 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include <osl/diagnose.h> +#include "base.hxx" + +#include "com/sun/star/uno/RuntimeException.hpp" + +using namespace com::sun::star; + +namespace stoc_rdbtdp +{ + +void SingletonTypeDescriptionImpl::init() { + { + MutexGuard guard(getMutex()); + if (_xInterfaceTD.is() || _xServiceTD.is()) { + return; + } + } + Reference< XTypeDescription > base; + try { + base = Reference< XTypeDescription >( + _xTDMgr->getByHierarchicalName(_aBaseName), UNO_QUERY_THROW); + } catch (NoSuchElementException const & e) { + throw RuntimeException( + (OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.container.NoSuchElementException: ")) + + e.Message), + static_cast< OWeakObject * >(this)); + } + MutexGuard guard(getMutex()); + if (!_xInterfaceTD.is() && !_xServiceTD.is()) { + if (resolveTypedefs(base)->getTypeClass() == TypeClass_INTERFACE) { + _xInterfaceTD = base; + } else if (base->getTypeClass() == TypeClass_SERVICE) { + _xServiceTD = Reference< XServiceTypeDescription >( + base, UNO_QUERY_THROW); + } else { + throw RuntimeException( + OUString( + RTL_CONSTASCII_USTRINGPARAM( + "Singleton is based on neither interface nor service")), + static_cast< OWeakObject * >(this)); + } + } + OSL_ASSERT(_xInterfaceTD.is() ^ _xServiceTD.is()); +} + +//__________________________________________________________________________________________________ +// virtual +SingletonTypeDescriptionImpl::~SingletonTypeDescriptionImpl() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +// XTypeDescription +//__________________________________________________________________________________________________ +// virtual +TypeClass SingletonTypeDescriptionImpl::getTypeClass() + throw(::com::sun::star::uno::RuntimeException) +{ + return TypeClass_SINGLETON; +} +//__________________________________________________________________________________________________ +// virtual +OUString SingletonTypeDescriptionImpl::getName() + throw(::com::sun::star::uno::RuntimeException) +{ + return _aName; +} + +// XSingletonTypeDescription +//__________________________________________________________________________________________________ +// virtual +Reference< XServiceTypeDescription > SAL_CALL +SingletonTypeDescriptionImpl::getService() + throw(::com::sun::star::uno::RuntimeException) +{ + init(); + return _xServiceTD; +} + +// XSingletonTypeDescription2 +//______________________________________________________________________________ +// virtual +sal_Bool SAL_CALL +SingletonTypeDescriptionImpl::isInterfaceBased() + throw(::com::sun::star::uno::RuntimeException) +{ + init(); + return _xInterfaceTD.is(); +} + +//______________________________________________________________________________ +// virtual +Reference< XTypeDescription > SAL_CALL +SingletonTypeDescriptionImpl::getInterface() + throw(::com::sun::star::uno::RuntimeException) +{ + init(); + return _xInterfaceTD; +} + +} diff --git a/stoc/source/security/access_controller.cxx b/stoc/source/security/access_controller.cxx new file mode 100644 index 000000000000..c7b1779a5a87 --- /dev/null +++ b/stoc/source/security/access_controller.cxx @@ -0,0 +1,1061 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include <vector> +#include <memory> + +#include <osl/diagnose.h> +#include <osl/interlck.h> +#include <osl/mutex.hxx> +#include <osl/thread.hxx> + +#include <rtl/ustrbuf.hxx> +#include <rtl/string.hxx> + +#include <uno/current_context.h> + +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/compbase3.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/implementationentry.hxx> + +#include <com/sun/star/uno/XCurrentContext.hpp> +#include <com/sun/star/uno/DeploymentException.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/security/XAccessController.hpp> +#include <com/sun/star/security/XPolicy.hpp> + +#include "lru_cache.h" +#include "permissions.h" + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) +#define SERVICE_NAME "com.sun.star.security.AccessController" +#define IMPL_NAME "com.sun.star.security.comp.stoc.AccessController" +#define USER_CREDS "access-control.user-credentials" + + +using namespace ::std; +using namespace ::osl; +using namespace ::cppu; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::rtl::OString; + +extern ::rtl_StandardModuleCount g_moduleCount; + +namespace stoc_sec +{ +// static stuff initialized when loading lib +static OUString s_envType = OUSTR(CPPU_CURRENT_LANGUAGE_BINDING_NAME); +static OUString s_implName = OUSTR(IMPL_NAME); +static OUString s_serviceName = OUSTR(SERVICE_NAME); +static OUString s_acRestriction = OUSTR("access-control.restriction"); + +static Sequence< OUString > s_serviceNames = Sequence< OUString >( &s_serviceName, 1 ); + +//################################################################################################## + +/** ac context intersects permissions of two ac contexts +*/ +class acc_Intersection + : public WeakImplHelper1< security::XAccessControlContext > +{ + Reference< security::XAccessControlContext > m_x1, m_x2; + + inline acc_Intersection( + Reference< security::XAccessControlContext > const & x1, + Reference< security::XAccessControlContext > const & x2 ) + SAL_THROW( () ); + +public: + virtual ~acc_Intersection() + SAL_THROW( () ); + + static inline Reference< security::XAccessControlContext > create( + Reference< security::XAccessControlContext > const & x1, + Reference< security::XAccessControlContext > const & x2 ) + SAL_THROW( () ); + + // XAccessControlContext impl + virtual void SAL_CALL checkPermission( + Any const & perm ) + throw (RuntimeException); +}; +//__________________________________________________________________________________________________ +inline acc_Intersection::acc_Intersection( + Reference< security::XAccessControlContext > const & x1, + Reference< security::XAccessControlContext > const & x2 ) + SAL_THROW( () ) + : m_x1( x1 ) + , m_x2( x2 ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); +} +//__________________________________________________________________________________________________ +acc_Intersection::~acc_Intersection() + SAL_THROW( () ) +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} +//-------------------------------------------------------------------------------------------------- +inline Reference< security::XAccessControlContext > acc_Intersection::create( + Reference< security::XAccessControlContext > const & x1, + Reference< security::XAccessControlContext > const & x2 ) + SAL_THROW( () ) +{ + if (! x1.is()) + return x2; + if (! x2.is()) + return x1; + return new acc_Intersection( x1, x2 ); +} +//__________________________________________________________________________________________________ +void acc_Intersection::checkPermission( + Any const & perm ) + throw (RuntimeException) +{ + m_x1->checkPermission( perm ); + m_x2->checkPermission( perm ); +} + +/** ac context unifies permissions of two ac contexts +*/ +class acc_Union + : public WeakImplHelper1< security::XAccessControlContext > +{ + Reference< security::XAccessControlContext > m_x1, m_x2; + + inline acc_Union( + Reference< security::XAccessControlContext > const & x1, + Reference< security::XAccessControlContext > const & x2 ) + SAL_THROW( () ); + +public: + virtual ~acc_Union() + SAL_THROW( () ); + + static inline Reference< security::XAccessControlContext > create( + Reference< security::XAccessControlContext > const & x1, + Reference< security::XAccessControlContext > const & x2 ) + SAL_THROW( () ); + + // XAccessControlContext impl + virtual void SAL_CALL checkPermission( + Any const & perm ) + throw (RuntimeException); +}; +//__________________________________________________________________________________________________ +inline acc_Union::acc_Union( + Reference< security::XAccessControlContext > const & x1, + Reference< security::XAccessControlContext > const & x2 ) + SAL_THROW( () ) + : m_x1( x1 ) + , m_x2( x2 ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); +} +//__________________________________________________________________________________________________ +acc_Union::~acc_Union() + SAL_THROW( () ) +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} +//-------------------------------------------------------------------------------------------------- +inline Reference< security::XAccessControlContext > acc_Union::create( + Reference< security::XAccessControlContext > const & x1, + Reference< security::XAccessControlContext > const & x2 ) + SAL_THROW( () ) +{ + if (! x1.is()) + return Reference< security::XAccessControlContext >(); // unrestricted + if (! x2.is()) + return Reference< security::XAccessControlContext >(); // unrestricted + return new acc_Union( x1, x2 ); +} +//__________________________________________________________________________________________________ +void acc_Union::checkPermission( + Any const & perm ) + throw (RuntimeException) +{ + try + { + m_x1->checkPermission( perm ); + } + catch (security::AccessControlException &) + { + m_x2->checkPermission( perm ); + } +} + +/** ac context doing permission checks on static permissions +*/ +class acc_Policy + : public WeakImplHelper1< security::XAccessControlContext > +{ + PermissionCollection m_permissions; + +public: + inline acc_Policy( + PermissionCollection const & permissions ) + SAL_THROW( () ); + virtual ~acc_Policy() + SAL_THROW( () ); + + // XAccessControlContext impl + virtual void SAL_CALL checkPermission( + Any const & perm ) + throw (RuntimeException); +}; +//__________________________________________________________________________________________________ +inline acc_Policy::acc_Policy( + PermissionCollection const & permissions ) + SAL_THROW( () ) + : m_permissions( permissions ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); +} +//__________________________________________________________________________________________________ +acc_Policy::~acc_Policy() + SAL_THROW( () ) +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} +//__________________________________________________________________________________________________ +void acc_Policy::checkPermission( + Any const & perm ) + throw (RuntimeException) +{ + m_permissions.checkPermission( perm ); +} + +/** current context overriding dynamic ac restriction +*/ +class acc_CurrentContext + : public ImplHelper1< XCurrentContext > +{ + oslInterlockedCount m_refcount; + + Reference< XCurrentContext > m_xDelegate; + Any m_restriction; + +public: + inline acc_CurrentContext( + Reference< XCurrentContext > const & xDelegate, + Reference< security::XAccessControlContext > const & xRestriction ) + SAL_THROW( () ); + virtual ~acc_CurrentContext() SAL_THROW( () ); + + // XInterface impl + virtual void SAL_CALL acquire() + throw (); + virtual void SAL_CALL release() + throw (); + + // XCurrentContext impl + virtual Any SAL_CALL getValueByName( OUString const & name ) + throw (RuntimeException); +}; +//__________________________________________________________________________________________________ +inline acc_CurrentContext::acc_CurrentContext( + Reference< XCurrentContext > const & xDelegate, + Reference< security::XAccessControlContext > const & xRestriction ) + SAL_THROW( () ) + : m_refcount( 0 ) + , m_xDelegate( xDelegate ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + + if (xRestriction.is()) + { + m_restriction = makeAny( xRestriction ); + } + // return empty any otherwise on getValueByName(), not null interface +} +//__________________________________________________________________________________________________ +acc_CurrentContext::~acc_CurrentContext() + SAL_THROW( () ) +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} +//__________________________________________________________________________________________________ +void acc_CurrentContext::acquire() + throw () +{ + ::osl_incrementInterlockedCount( &m_refcount ); +} +//__________________________________________________________________________________________________ +void acc_CurrentContext::release() + throw () +{ + if (! ::osl_decrementInterlockedCount( &m_refcount )) + { + delete this; + } +} +//__________________________________________________________________________________________________ +Any acc_CurrentContext::getValueByName( OUString const & name ) + throw (RuntimeException) +{ + if (name.equals( s_acRestriction )) + { + return m_restriction; + } + else if (m_xDelegate.is()) + { + return m_xDelegate->getValueByName( name ); + } + else + { + return Any(); + } +} + +//################################################################################################## + +//-------------------------------------------------------------------------------------------------- +static inline void dispose( Reference< XInterface > const & x ) + SAL_THROW( (RuntimeException) ) +{ + Reference< lang::XComponent > xComp( x, UNO_QUERY ); + if (xComp.is()) + { + xComp->dispose(); + } +} +//-------------------------------------------------------------------------------------------------- +static inline Reference< security::XAccessControlContext > getDynamicRestriction( + Reference< XCurrentContext > const & xContext ) + SAL_THROW( (RuntimeException) ) +{ + if (xContext.is()) + { + Any acc( xContext->getValueByName( s_acRestriction ) ); + if (typelib_TypeClass_INTERFACE == acc.pType->eTypeClass) + { + // avoid ref-counting + OUString const & typeName = + *reinterpret_cast< OUString const * >( &acc.pType->pTypeName ); + if (typeName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("com.sun.star.security.XAccessControlContext") )) + { + return Reference< security::XAccessControlContext >( + *reinterpret_cast< security::XAccessControlContext ** const >( acc.pData ) ); + } + else // try to query + { + return Reference< security::XAccessControlContext >::query( + *reinterpret_cast< XInterface ** const >( acc.pData ) ); + } + } + } + return Reference< security::XAccessControlContext >(); +} +//================================================================================================== +class cc_reset +{ + void * m_cc; +public: + inline cc_reset( void * cc ) SAL_THROW( () ) + : m_cc( cc ) {} + inline ~cc_reset() SAL_THROW( () ) + { ::uno_setCurrentContext( m_cc, s_envType.pData, 0 ); } +}; + +//################################################################################################## + +struct MutexHolder +{ + Mutex m_mutex; +}; +typedef WeakComponentImplHelper3< + security::XAccessController, lang::XServiceInfo, lang::XInitialization > t_helper; + +//================================================================================================== +class AccessController + : public MutexHolder + , public t_helper +{ + Reference< XComponentContext > m_xComponentContext; + + Reference< security::XPolicy > m_xPolicy; + Reference< security::XPolicy > const & getPolicy() + SAL_THROW( (RuntimeException) ); + + // mode + enum Mode { OFF, ON, DYNAMIC_ONLY, SINGLE_USER, SINGLE_DEFAULT_USER } m_mode; + + PermissionCollection m_defaultPermissions; + // for single-user mode + PermissionCollection m_singleUserPermissions; + OUString m_singleUserId; + bool m_defaultPerm_init; + bool m_singleUser_init; + // for multi-user mode + lru_cache< OUString, PermissionCollection, ::rtl::OUStringHash, equal_to< OUString > > + m_user2permissions; + + ThreadData m_rec; + typedef vector< pair< OUString, Any > > t_rec_vec; + inline void clearPostPoned() SAL_THROW( () ); + void checkAndClearPostPoned() SAL_THROW( (RuntimeException) ); + + PermissionCollection getEffectivePermissions( + Reference< XCurrentContext > const & xContext, + Any const & demanded_perm ) + SAL_THROW( (RuntimeException) ); + +protected: + virtual void SAL_CALL disposing(); + +public: + AccessController( Reference< XComponentContext > const & xComponentContext ) + SAL_THROW( (RuntimeException) ); + virtual ~AccessController() + SAL_THROW( () ); + + // XInitialization impl + virtual void SAL_CALL initialize( + Sequence< Any > const & arguments ) + throw (Exception); + + // XAccessController impl + virtual void SAL_CALL checkPermission( + Any const & perm ) + throw (RuntimeException); + virtual Any SAL_CALL doRestricted( + Reference< security::XAction > const & xAction, + Reference< security::XAccessControlContext > const & xRestriction ) + throw (Exception); + virtual Any SAL_CALL doPrivileged( + Reference< security::XAction > const & xAction, + Reference< security::XAccessControlContext > const & xRestriction ) + throw (Exception); + virtual Reference< security::XAccessControlContext > SAL_CALL getContext() + throw (RuntimeException); + + // XServiceInfo impl + virtual OUString SAL_CALL getImplementationName() + throw (RuntimeException); + virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName ) + throw (RuntimeException); + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() + throw (RuntimeException); +}; +//__________________________________________________________________________________________________ +AccessController::AccessController( Reference< XComponentContext > const & xComponentContext ) + SAL_THROW( (RuntimeException) ) + : t_helper( m_mutex ) + , m_xComponentContext( xComponentContext ) + , m_mode( ON ) // default + , m_defaultPerm_init( false ) + , m_singleUser_init( false ) + , m_rec( 0 ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + + OUString mode; + if (m_xComponentContext->getValueByName( OUSTR("/services/" SERVICE_NAME "/mode") ) >>= mode) + { + if (mode.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("off") )) + { + m_mode = OFF; + } + else if (mode.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("on") )) + { + m_mode = ON; + } + else if (mode.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("dynamic-only") )) + { + m_mode = DYNAMIC_ONLY; + } + else if (mode.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("single-user") )) + { + m_xComponentContext->getValueByName( + OUSTR("/services/" SERVICE_NAME "/single-user-id") ) >>= m_singleUserId; + if (! m_singleUserId.getLength()) + { + throw RuntimeException( + OUSTR("expected a user id in component context entry " + "\"/services/" SERVICE_NAME "/single-user-id\"!"), + (OWeakObject *)this ); + } + m_mode = SINGLE_USER; + } + else if (mode.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("single-default-user") )) + { + m_mode = SINGLE_DEFAULT_USER; + } + } + + // switch on caching for DYNAMIC_ONLY and ON (sharable multi-user process) + if (ON == m_mode || DYNAMIC_ONLY == m_mode) + { + sal_Int32 cacheSize = 0; // multi-user cache size + if (! (m_xComponentContext->getValueByName( + OUSTR("/services/" SERVICE_NAME "/user-cache-size") ) >>= cacheSize)) + { + cacheSize = 128; // reasonable default? + } +#ifdef __CACHE_DIAGNOSE + cacheSize = 2; +#endif + m_user2permissions.setSize( cacheSize ); + } +} +//__________________________________________________________________________________________________ +AccessController::~AccessController() + SAL_THROW( () ) +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} +//__________________________________________________________________________________________________ +void AccessController::disposing() +{ + m_mode = OFF; // avoid checks from now on xxx todo review/ better DYNAMIC_ONLY? + m_xPolicy.clear(); + m_xComponentContext.clear(); +} + +// XInitialization impl +//__________________________________________________________________________________________________ +void AccessController::initialize( + Sequence< Any > const & arguments ) + throw (Exception) +{ + // xxx todo: review for forking + // portal forking hack: re-initialize for another user-id + if (SINGLE_USER != m_mode) // only if in single-user mode + { + throw RuntimeException( + OUSTR("invalid call: ac must be in \"single-user\" mode!"), (OWeakObject *)this ); + } + OUString userId; + arguments[ 0 ] >>= userId; + if (! userId.getLength()) + { + throw RuntimeException( + OUSTR("expected a user-id as first argument!"), (OWeakObject *)this ); + } + // assured that no sync is necessary: no check happens at this forking time + m_singleUserId = userId; + m_singleUser_init = false; +} + +//__________________________________________________________________________________________________ +Reference< security::XPolicy > const & AccessController::getPolicy() + SAL_THROW( (RuntimeException) ) +{ + // get policy singleton + if (! m_xPolicy.is()) + { + Reference< security::XPolicy > xPolicy; + m_xComponentContext->getValueByName( + OUSTR("/singletons/com.sun.star.security.thePolicy") ) >>= xPolicy; + if (xPolicy.is()) + { + MutexGuard guard( m_mutex ); + if (! m_xPolicy.is()) + { + m_xPolicy = xPolicy; + } + } + else + { + throw SecurityException( + OUSTR("cannot get policy singleton!"), (OWeakObject *)this ); + } + } + return m_xPolicy; +} + +#ifdef __DIAGNOSE +static void dumpPermissions( + PermissionCollection const & collection, OUString const & userId = OUString() ) SAL_THROW( () ) +{ + OUStringBuffer buf( 48 ); + if (userId.getLength()) + { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("> dumping permissions of user \"") ); + buf.append( userId ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\":") ); + } + else + { + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("> dumping default permissions:") ); + } + OString str( ::rtl::OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( str.getStr() ); + Sequence< OUString > permissions( collection.toStrings() ); + OUString const * p = permissions.getConstArray(); + for ( sal_Int32 nPos = 0; nPos < permissions.getLength(); ++nPos ) + { + OString str( ::rtl::OUStringToOString( p[ nPos ], RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( str.getStr() ); + } + OSL_TRACE( "> permission dump done" ); +} +#endif + + +//__________________________________________________________________________________________________ +inline void AccessController::clearPostPoned() SAL_THROW( () ) +{ + delete reinterpret_cast< t_rec_vec * >( m_rec.getData() ); + m_rec.setData( 0 ); +} +//__________________________________________________________________________________________________ +void AccessController::checkAndClearPostPoned() SAL_THROW( (RuntimeException) ) +{ + // check postponed permissions + auto_ptr< t_rec_vec > rec( reinterpret_cast< t_rec_vec * >( m_rec.getData() ) ); + m_rec.setData( 0 ); // takeover ownership + OSL_ASSERT( rec.get() ); + if (rec.get()) + { + t_rec_vec const & vec = *rec.get(); + switch (m_mode) + { + case SINGLE_USER: + { + OSL_ASSERT( m_singleUser_init ); + for ( size_t nPos = 0; nPos < vec.size(); ++nPos ) + { + pair< OUString, Any > const & p = vec[ nPos ]; + OSL_ASSERT( m_singleUserId.equals( p.first ) ); + m_singleUserPermissions.checkPermission( p.second ); + } + break; + } + case SINGLE_DEFAULT_USER: + { + OSL_ASSERT( m_defaultPerm_init ); + for ( size_t nPos = 0; nPos < vec.size(); ++nPos ) + { + pair< OUString, Any > const & p = vec[ nPos ]; + OSL_ASSERT( !p.first.getLength() ); // default-user + m_defaultPermissions.checkPermission( p.second ); + } + break; + } + case ON: + { + for ( size_t nPos = 0; nPos < vec.size(); ++nPos ) + { + pair< OUString, Any > const & p = vec[ nPos ]; + PermissionCollection const * pPermissions; + // lookup policy for user + { + MutexGuard guard( m_mutex ); + pPermissions = m_user2permissions.lookup( p.first ); + } + OSL_ASSERT( pPermissions ); + if (pPermissions) + { + pPermissions->checkPermission( p.second ); + } + } + break; + } + default: + OSL_ENSURE( 0, "### this should never be called in this ac mode!" ); + break; + } + } +} +//__________________________________________________________________________________________________ +/** this is the only function calling the policy singleton and thus has to take care + of recurring calls! + + @param demanded_perm (if not empty) is the demanded permission of a checkPermission() call + which will be postponed for recurring calls +*/ +PermissionCollection AccessController::getEffectivePermissions( + Reference< XCurrentContext > const & xContext, + Any const & demanded_perm ) + SAL_THROW( (RuntimeException) ) +{ + OUString userId; + + switch (m_mode) + { + case SINGLE_USER: + { + if (m_singleUser_init) + return m_singleUserPermissions; + userId = m_singleUserId; + break; + } + case SINGLE_DEFAULT_USER: + { + if (m_defaultPerm_init) + return m_defaultPermissions; + break; + } + case ON: + { + if (xContext.is()) + { + xContext->getValueByName( OUSTR(USER_CREDS ".id") ) >>= userId; + } + if (! userId.getLength()) + { + throw SecurityException( + OUSTR("cannot determine current user in multi-user ac!"), (OWeakObject *)this ); + } + + // lookup policy for user + MutexGuard guard( m_mutex ); + PermissionCollection const * pPermissions = m_user2permissions.lookup( userId ); + if (pPermissions) + return *pPermissions; + break; + } + default: + OSL_ENSURE( 0, "### this should never be called in this ac mode!" ); + return PermissionCollection(); + } + + // call on policy + // iff this is a recurring call for the default user, then grant all permissions + t_rec_vec * rec = reinterpret_cast< t_rec_vec * >( m_rec.getData() ); + if (rec) // tls entry exists => this is recursive call + { + if (demanded_perm.hasValue()) + { + // enqueue + rec->push_back( pair< OUString, Any >( userId, demanded_perm ) ); + } +#ifdef __DIAGNOSE + OUStringBuffer buf( 48 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("> info: recurring call of user \"") ); + buf.append( userId ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"") ); + OString str( + ::rtl::OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( str.getStr() ); +#endif + return PermissionCollection( new AllPermission() ); + } + else // no tls + { + rec = new t_rec_vec; + m_rec.setData( rec ); + } + + try // calls on API + { + // init default permissions + if (! m_defaultPerm_init) + { + PermissionCollection defaultPermissions( + getPolicy()->getDefaultPermissions() ); + // assign + MutexGuard guard( m_mutex ); + if (! m_defaultPerm_init) + { + m_defaultPermissions = defaultPermissions; + m_defaultPerm_init = true; + } +#ifdef __DIAGNOSE + dumpPermissions( m_defaultPermissions ); +#endif + } + + PermissionCollection ret; + + // init user permissions + switch (m_mode) + { + case SINGLE_USER: + { + ret = PermissionCollection( + getPolicy()->getPermissions( userId ), m_defaultPermissions ); + { + // assign + MutexGuard guard( m_mutex ); + if (m_singleUser_init) + { + ret = m_singleUserPermissions; + } + else + { + m_singleUserPermissions = ret; + m_singleUser_init = true; + } + } +#ifdef __DIAGNOSE + dumpPermissions( ret, userId ); +#endif + break; + } + case SINGLE_DEFAULT_USER: + { + ret = m_defaultPermissions; + break; + } + case ON: + { + ret = PermissionCollection( + getPolicy()->getPermissions( userId ), m_defaultPermissions ); + { + // cache + MutexGuard guard( m_mutex ); + m_user2permissions.set( userId, ret ); + } +#ifdef __DIAGNOSE + dumpPermissions( ret, userId ); +#endif + break; + } + default: + break; + } + + // check postponed + checkAndClearPostPoned(); + return ret; + } + catch (security::AccessControlException & exc) // wrapped into DeploymentException + { + clearPostPoned(); // safety: exception could have happened before checking postponed? + OUStringBuffer buf( 64 ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("deployment error (AccessControlException occured): ") ); + buf.append( exc.Message ); + throw DeploymentException( buf.makeStringAndClear(), exc.Context ); + } + catch (RuntimeException &) + { + // dont check postponed, just cleanup + clearPostPoned(); + delete reinterpret_cast< t_rec_vec * >( m_rec.getData() ); + m_rec.setData( 0 ); + throw; + } + catch (Exception &) + { + // check postponed permissions first + // => AccessControlExceptions are errors, user exceptions not! + checkAndClearPostPoned(); + throw; + } + catch (...) + { + // dont check postponed, just cleanup + clearPostPoned(); + throw; + } +} + +// XAccessController impl +//__________________________________________________________________________________________________ +void AccessController::checkPermission( + Any const & perm ) + throw (RuntimeException) +{ + if (rBHelper.bDisposed) + { + throw lang::DisposedException( + OUSTR("checkPermission() call on disposed AccessController!"), (OWeakObject *)this ); + } + + if (OFF == m_mode) + return; + + // first dynamic check of ac contexts + Reference< XCurrentContext > xContext; + ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 ); + Reference< security::XAccessControlContext > xACC( getDynamicRestriction( xContext ) ); + if (xACC.is()) + { + xACC->checkPermission( perm ); + } + + if (DYNAMIC_ONLY == m_mode) + return; + + // then static check + getEffectivePermissions( xContext, perm ).checkPermission( perm ); +} +//__________________________________________________________________________________________________ +Any AccessController::doRestricted( + Reference< security::XAction > const & xAction, + Reference< security::XAccessControlContext > const & xRestriction ) + throw (Exception) +{ + if (rBHelper.bDisposed) + { + throw lang::DisposedException( + OUSTR("doRestricted() call on disposed AccessController!"), (OWeakObject *)this ); + } + + if (OFF == m_mode) // optimize this way, because no dynamic check will be performed + return xAction->run(); + + if (xRestriction.is()) + { + Reference< XCurrentContext > xContext; + ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 ); + + // override restriction + Reference< XCurrentContext > xNewContext( + new acc_CurrentContext( xContext, acc_Intersection::create( + xRestriction, getDynamicRestriction( xContext ) ) ) ); + ::uno_setCurrentContext( xNewContext.get(), s_envType.pData, 0 ); + cc_reset reset( xContext.get() ); + return xAction->run(); + } + else + { + return xAction->run(); + } +} +//__________________________________________________________________________________________________ +Any AccessController::doPrivileged( + Reference< security::XAction > const & xAction, + Reference< security::XAccessControlContext > const & xRestriction ) + throw (Exception) +{ + if (rBHelper.bDisposed) + { + throw lang::DisposedException( + OUSTR("doPrivileged() call on disposed AccessController!"), (OWeakObject *)this ); + } + + if (OFF == m_mode) // no dynamic check will be performed + { + return xAction->run(); + } + + Reference< XCurrentContext > xContext; + ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 ); + + Reference< security::XAccessControlContext > xOldRestr( + getDynamicRestriction( xContext ) ); + + if (xOldRestr.is()) // previous restriction + { + // override restriction + Reference< XCurrentContext > xNewContext( + new acc_CurrentContext( xContext, acc_Union::create( xRestriction, xOldRestr ) ) ); + ::uno_setCurrentContext( xNewContext.get(), s_envType.pData, 0 ); + cc_reset reset( xContext.get() ); + return xAction->run(); + } + else // no previous restriction => never current restriction + { + return xAction->run(); + } +} +//__________________________________________________________________________________________________ +Reference< security::XAccessControlContext > AccessController::getContext() + throw (RuntimeException) +{ + if (rBHelper.bDisposed) + { + throw lang::DisposedException( + OUSTR("getContext() call on disposed AccessController!"), (OWeakObject *)this ); + } + + if (OFF == m_mode) // optimize this way, because no dynamic check will be performed + { + return new acc_Policy( PermissionCollection( new AllPermission() ) ); + } + + Reference< XCurrentContext > xContext; + ::uno_getCurrentContext( (void **)&xContext, s_envType.pData, 0 ); + + return acc_Intersection::create( + getDynamicRestriction( xContext ), + new acc_Policy( getEffectivePermissions( xContext, Any() ) ) ); +} + +// XServiceInfo impl +//__________________________________________________________________________________________________ +OUString AccessController::getImplementationName() + throw (RuntimeException) +{ + return s_implName; +} +//__________________________________________________________________________________________________ +sal_Bool AccessController::supportsService( OUString const & serviceName ) + throw (RuntimeException) +{ + OUString const * pNames = s_serviceNames.getConstArray(); + for ( sal_Int32 nPos = s_serviceNames.getLength(); nPos--; ) + { + if (serviceName.equals( pNames[ nPos ] )) + { + return sal_True; + } + } + return sal_False; +} +//__________________________________________________________________________________________________ +Sequence< OUString > AccessController::getSupportedServiceNames() + throw (RuntimeException) +{ + return s_serviceNames; +} +} +//################################################################################################## +namespace stoc_bootstrap { +//-------------------------------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL ac_create( + Reference< XComponentContext > const & xComponentContext ) + SAL_THROW( (Exception) ) +{ + return (OWeakObject *)new stoc_sec::AccessController( xComponentContext ); +} +//-------------------------------------------------------------------------------------------------- +Sequence< OUString > ac_getSupportedServiceNames() SAL_THROW( () ) +{ + return stoc_sec::s_serviceNames; +} +//-------------------------------------------------------------------------------------------------- +OUString ac_getImplementationName() SAL_THROW( () ) +{ + return stoc_sec::s_implName; +} +//-------------------------------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL filepolicy_create( + Reference< XComponentContext > const & xComponentContext ) + SAL_THROW( (Exception) ); +//-------------------------------------------------------------------------------------------------- +Sequence< OUString > filepolicy_getSupportedServiceNames() SAL_THROW( () ); +//-------------------------------------------------------------------------------------------------- +OUString filepolicy_getImplementationName() SAL_THROW( () ); +} diff --git a/stoc/source/security/file_policy.cxx b/stoc/source/security/file_policy.cxx new file mode 100644 index 000000000000..b59502852d1d --- /dev/null +++ b/stoc/source/security/file_policy.cxx @@ -0,0 +1,603 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include <hash_map> + +#include <osl/diagnose.h> +#include <osl/file.h> +#include <rtl/byteseq.hxx> +#include <rtl/string.hxx> +#include <rtl/ustrbuf.hxx> + +#include <cppuhelper/access_control.hxx> +#include <cppuhelper/compbase2.hxx> +#include <cppuhelper/implementationentry.hxx> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/security/XAccessController.hpp> +#include <com/sun/star/security/XPolicy.hpp> +#include <com/sun/star/security/AllPermission.hpp> +#include <com/sun/star/security/RuntimePermission.hpp> +#include <com/sun/star/io/FilePermission.hpp> +#include <com/sun/star/connection/SocketPermission.hpp> + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) +#define SERVICE_NAME "com.sun.star.security.Policy" +#define IMPL_NAME "com.sun.star.security.comp.stoc.FilePolicy" + + +using namespace ::osl; +using namespace ::rtl; +using namespace ::cppu; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +extern ::rtl_StandardModuleCount g_moduleCount; + +namespace stoc_sec +{ +// static stuff initialized when loading lib +static OUString s_implName = OUSTR(IMPL_NAME); +static OUString s_serviceName = OUSTR(SERVICE_NAME); + +static Sequence< OUString > s_serviceNames = Sequence< OUString >( &s_serviceName, 1 ); +//################################################################################################## + +//-------------------------------------------------------------------------------------------------- +static inline void dispose( Reference< XInterface > const & x ) + SAL_THROW( (RuntimeException) ) +{ + Reference< lang::XComponent > xComp( x, UNO_QUERY ); + if (xComp.is()) + { + xComp->dispose(); + } +} + +//################################################################################################## + +struct MutexHolder +{ + Mutex m_mutex; +}; +typedef WeakComponentImplHelper2< security::XPolicy, lang::XServiceInfo > t_helper; + +//================================================================================================== +class FilePolicy + : public MutexHolder + , public t_helper +{ + Reference< XComponentContext > m_xComponentContext; + AccessControl m_ac; + + Sequence< Any > m_defaultPermissions; + typedef std::hash_map< OUString, Sequence< Any >, OUStringHash > t_permissions; + t_permissions m_userPermissions; + bool m_init; + +protected: + virtual void SAL_CALL disposing(); + +public: + FilePolicy( Reference< XComponentContext > const & xComponentContext ) + SAL_THROW( () ); + virtual ~FilePolicy() + SAL_THROW( () ); + + // XPolicy impl + virtual Sequence< Any > SAL_CALL getPermissions( + OUString const & userId ) + throw (RuntimeException); + virtual Sequence< Any > SAL_CALL getDefaultPermissions() + throw (RuntimeException); + virtual void SAL_CALL refresh() + throw (RuntimeException); + + // XServiceInfo impl + virtual OUString SAL_CALL getImplementationName() + throw (RuntimeException); + virtual sal_Bool SAL_CALL supportsService( OUString const & serviceName ) + throw (RuntimeException); + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() + throw (RuntimeException); +}; +//__________________________________________________________________________________________________ +FilePolicy::FilePolicy( Reference< XComponentContext > const & xComponentContext ) + SAL_THROW( () ) + : t_helper( m_mutex ) + , m_xComponentContext( xComponentContext ) + , m_ac( xComponentContext ) + , m_init( false ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); +} +//__________________________________________________________________________________________________ +FilePolicy::~FilePolicy() + SAL_THROW( () ) +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} +//__________________________________________________________________________________________________ +void FilePolicy::disposing() +{ + m_userPermissions.clear(); + m_defaultPermissions = Sequence< Any >(); + m_xComponentContext.clear(); +} + +//__________________________________________________________________________________________________ +Sequence< Any > FilePolicy::getPermissions( + OUString const & userId ) + throw (RuntimeException) +{ + if (! m_init) + { + refresh(); + m_init = true; + } + + MutexGuard guard( m_mutex ); + t_permissions::iterator iFind( m_userPermissions.find( userId ) ); + if (m_userPermissions.end() == iFind) + { + return Sequence< Any >(); + } + else + { + return iFind->second; + } +} +//__________________________________________________________________________________________________ +Sequence< Any > FilePolicy::getDefaultPermissions() + throw (RuntimeException) +{ + if (! m_init) + { + refresh(); + m_init = true; + } + + MutexGuard guard( m_mutex ); + return m_defaultPermissions; +} + +//================================================================================================== +class PolicyReader +{ + OUString m_fileName; + oslFileHandle m_file; + + sal_Int32 m_linepos; + ByteSequence m_line; + sal_Int32 m_pos; + sal_Unicode m_back; + + sal_Unicode get() + SAL_THROW( (RuntimeException) ); + inline void back( sal_Unicode c ) SAL_THROW( () ) + { m_back = c; } + + inline bool isWhiteSpace( sal_Unicode c ) SAL_THROW( () ) + { return (' ' == c || '\t' == c || '\n' == c || '\r' == c); } + void skipWhiteSpace() + SAL_THROW( (RuntimeException) ); + + inline bool isCharToken( sal_Unicode c ) SAL_THROW( () ) + { return (';' == c || ',' == c || '{' == c || '}' == c); } + +public: + PolicyReader( OUString const & file, AccessControl & ac ) + SAL_THROW( (RuntimeException) ); + ~PolicyReader() + SAL_THROW( () ); + + void error( OUString const & msg ) + SAL_THROW( (RuntimeException) ); + + OUString getToken() + SAL_THROW( (RuntimeException) ); + OUString assureToken() + SAL_THROW( (RuntimeException) ); + OUString getQuotedToken() + SAL_THROW( (RuntimeException) ); + OUString assureQuotedToken() + SAL_THROW( (RuntimeException) ); + void assureToken( sal_Unicode token ) + SAL_THROW( (RuntimeException) ); +}; +//__________________________________________________________________________________________________ +void PolicyReader::assureToken( sal_Unicode token ) + SAL_THROW( (RuntimeException) ) +{ + skipWhiteSpace(); + sal_Unicode c = get(); + if (c == token) + return; + OUStringBuffer buf( 16 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("expected >") ); + buf.append( c ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("<!") ); + error( buf.makeStringAndClear() ); +} +//__________________________________________________________________________________________________ +OUString PolicyReader::assureQuotedToken() + SAL_THROW( (RuntimeException) ) +{ + OUString token( getQuotedToken() ); + if (! token.getLength()) + error( OUSTR("unexpected end of file!") ); + return token; +} +//__________________________________________________________________________________________________ +OUString PolicyReader::getQuotedToken() + SAL_THROW( (RuntimeException) ) +{ + skipWhiteSpace(); + OUStringBuffer buf( 32 ); + sal_Unicode c = get(); + if ('\"' != c) + error( OUSTR("expected quoting >\"< character!") ); + c = get(); + while ('\0' != c && '\"' != c) + { + buf.append( c ); + c = get(); + } + return buf.makeStringAndClear(); +} +//__________________________________________________________________________________________________ +OUString PolicyReader::assureToken() + SAL_THROW( (RuntimeException) ) +{ + OUString token( getToken() ); + if (! token.getLength()) + error( OUSTR("unexpected end of file!") ); + return token; +} +//__________________________________________________________________________________________________ +OUString PolicyReader::getToken() + SAL_THROW( (RuntimeException) ) +{ + skipWhiteSpace(); + sal_Unicode c = get(); + if (isCharToken( c )) + return OUString( &c, 1 ); + OUStringBuffer buf( 32 ); + while ('\0' != c && !isCharToken( c ) && !isWhiteSpace( c )) + { + buf.append( c ); + c = get(); + } + back( c ); + return buf.makeStringAndClear(); +} +//__________________________________________________________________________________________________ +void PolicyReader::skipWhiteSpace() + SAL_THROW( (RuntimeException) ) +{ + sal_Unicode c; + do + { + c = get(); + } + while (isWhiteSpace( c )); // seeking next non-whitespace char + + if ('/' == c) // C/C++ like comment + { + c = get(); + if ('/' == c) // C++ like comment + { + do + { + c = get(); + } + while ('\n' != c && '\0' != c); // seek eol/eof + skipWhiteSpace(); // cont skip on next line + } + else if ('*' == c) // C like comment + { + bool fini = true; + do + { + c = get(); + if ('*' == c) + { + c = get(); + fini = ('/' == c || '\0' == c); + } + else + { + fini = ('\0' == c); + } + } + while (! fini); + skipWhiteSpace(); // cont skip on next line + } + else + { + error( OUSTR("expected C/C++ like comment!") ); + } + } + else if ('#' == c) // script like comment + { + do + { + c = get(); + } + while ('\n' != c && '\0' != c); // seek eol/eof + skipWhiteSpace(); // cont skip on next line + } + + else // is token char + { + back( c ); + } +} +//__________________________________________________________________________________________________ +sal_Unicode PolicyReader::get() + SAL_THROW( (RuntimeException) ) +{ + if ('\0' != m_back) // one char push back possible + { + sal_Unicode c = m_back; + m_back = '\0'; + return c; + } + else if (m_pos == m_line.getLength()) // provide newline as whitespace + { + ++m_pos; + return '\n'; + } + else if (m_pos > m_line.getLength()) // read new line + { + sal_Bool eof; + oslFileError rc = ::osl_isEndOfFile( m_file, &eof ); + if (osl_File_E_None != rc) + error( OUSTR("checking eof failed!") ); + if (eof) + return '\0'; + + rc = ::osl_readLine( m_file, reinterpret_cast< sal_Sequence ** >( &m_line ) ); + if (osl_File_E_None != rc) + error( OUSTR("read line failed!") ); + ++m_linepos; + if (! m_line.getLength()) // empty line read + { + m_pos = 1; // read new line next time + return '\n'; + } + m_pos = 0; + } + return (m_line.getConstArray()[ m_pos++ ]); +} +//__________________________________________________________________________________________________ +void PolicyReader::error( OUString const & msg ) + SAL_THROW( (RuntimeException) ) +{ + OUStringBuffer buf( 32 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("error processing file \"") ); + buf.append( m_fileName ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" [line ") ); + buf.append( m_linepos ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", column ") ); + buf.append( m_pos ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] ") ); + buf.append( msg ); + throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface >() ); +} +//__________________________________________________________________________________________________ +PolicyReader::PolicyReader( OUString const & fileName, AccessControl & ac ) + SAL_THROW( (RuntimeException) ) + : m_fileName( fileName ) + , m_linepos( 0 ) + , m_pos( 1 ) // force readline + , m_back( '\0' ) +{ + ac.checkFilePermission( m_fileName, OUSTR("read") ); + if (osl_File_E_None != ::osl_openFile( m_fileName.pData, &m_file, osl_File_OpenFlag_Read )) + { + OUStringBuffer buf( 32 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("cannot open file \"") ); + buf.append( m_fileName ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") ); + throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface >() ); + } +} +//__________________________________________________________________________________________________ +PolicyReader::~PolicyReader() + SAL_THROW( () ) +{ + if ( ::osl_closeFile( m_file ) != osl_File_E_None ) { + OSL_ASSERT( false ); + } +} + +static OUString s_grant = OUSTR("grant"); +static OUString s_user = OUSTR("user"); +static OUString s_permission = OUSTR("permission"); +static OUString s_openBrace = OUSTR("{"); +static OUString s_closingBrace = OUSTR("}"); + +static OUString s_filePermission = OUSTR("com.sun.star.io.FilePermission"); +static OUString s_socketPermission = OUSTR("com.sun.star.connection.SocketPermission"); +static OUString s_runtimePermission = OUSTR("com.sun.star.security.RuntimePermission"); +static OUString s_allPermission = OUSTR("com.sun.star.security.AllPermission"); + +//__________________________________________________________________________________________________ +void FilePolicy::refresh() + throw (RuntimeException) +{ + // read out file + OUString fileName; + m_xComponentContext->getValueByName( + OUSTR("/implementations/" IMPL_NAME "/file-name") ) >>= fileName; + if (! fileName.getLength()) + { + throw RuntimeException( + OUSTR("name of policy file unknown!"), + (OWeakObject *)this ); + } + + PolicyReader reader( fileName, m_ac ); + + // fill these two + Sequence< Any > defaultPermissions; + t_permissions userPermissions; + + OUString token( reader.getToken() ); + while (token.getLength()) + { + if (! token.equals( s_grant )) + reader.error( OUSTR("expected >grant< token!") ); + OUString userId; + token = reader.assureToken(); + if (token.equals( s_user )) // next token is user-id + { + userId = reader.assureQuotedToken(); + token = reader.assureToken(); + } + if (! token.equals( s_openBrace )) + reader.error( OUSTR("expected opening brace >{<!") ); + token = reader.assureToken(); + // permissions list + while (! token.equals( s_closingBrace )) + { + if (! token.equals( s_permission )) + reader.error( OUSTR("expected >permission< or closing brace >}<!") ); + + token = reader.assureToken(); // permission type + Any perm; + if (token.equals( s_filePermission )) // FilePermission + { + OUString url( reader.assureQuotedToken() ); + reader.assureToken( ',' ); + OUString actions( reader.assureQuotedToken() ); + perm <<= io::FilePermission( url, actions ); + } + else if (token.equals( s_socketPermission )) // SocketPermission + { + OUString host( reader.assureQuotedToken() ); + reader.assureToken( ',' ); + OUString actions( reader.assureQuotedToken() ); + perm <<= connection::SocketPermission( host, actions ); + } + else if (token.equals( s_runtimePermission )) // RuntimePermission + { + OUString name( reader.assureQuotedToken() ); + perm <<= security::RuntimePermission( name ); + } + else if (token.equals( s_allPermission )) // AllPermission + { + perm <<= security::AllPermission(); + } + else + { + reader.error( OUSTR("expected permission type!") ); + } + + reader.assureToken( ';' ); + + // insert + if (userId.getLength()) + { + Sequence< Any > perms( userPermissions[ userId ] ); + sal_Int32 len = perms.getLength(); + perms.realloc( len +1 ); + perms[ len ] = perm; + userPermissions[ userId ] = perms; + } + else + { + sal_Int32 len = defaultPermissions.getLength(); + defaultPermissions.realloc( len +1 ); + defaultPermissions[ len ] = perm; + } + + token = reader.assureToken(); // next permissions token + } + + reader.assureToken( ';' ); // semi + token = reader.getToken(); // next grant token + } + + // assign new ones + MutexGuard guard( m_mutex ); + m_defaultPermissions = defaultPermissions; + m_userPermissions = userPermissions; +} + +//__________________________________________________________________________________________________ +OUString FilePolicy::getImplementationName() + throw (RuntimeException) +{ + return s_implName; +} +//__________________________________________________________________________________________________ +sal_Bool FilePolicy::supportsService( OUString const & serviceName ) + throw (RuntimeException) +{ + OUString const * pNames = s_serviceNames.getConstArray(); + for ( sal_Int32 nPos = s_serviceNames.getLength(); nPos--; ) + { + if (serviceName.equals( pNames[ nPos ] )) + { + return sal_True; + } + } + return sal_False; +} +//__________________________________________________________________________________________________ +Sequence< OUString > FilePolicy::getSupportedServiceNames() + throw (RuntimeException) +{ + return s_serviceNames; +} +} +//################################################################################################## +namespace stoc_bootstrap +{ +//-------------------------------------------------------------------------------------------------- +Reference< XInterface > SAL_CALL filepolicy_create( + Reference< XComponentContext > const & xComponentContext ) + SAL_THROW( (Exception) ) +{ + return (OWeakObject *)new stoc_sec::FilePolicy( xComponentContext ); +} +//-------------------------------------------------------------------------------------------------- +Sequence< OUString > filepolicy_getSupportedServiceNames() SAL_THROW( () ) +{ + return stoc_sec::s_serviceNames; +} +//-------------------------------------------------------------------------------------------------- +OUString filepolicy_getImplementationName() SAL_THROW( () ) +{ + return stoc_sec::s_implName; +} +} diff --git a/stoc/source/security/lru_cache.h b/stoc/source/security/lru_cache.h new file mode 100644 index 000000000000..3f2312a67aab --- /dev/null +++ b/stoc/source/security/lru_cache.h @@ -0,0 +1,279 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _STOC_SEC_LRU_CACHE_H_ +#define _STOC_SEC_LRU_CACHE_H_ + +#include <hash_map> + +// __CACHE_DIAGNOSE works only for OUString keys +#ifdef __CACHE_DIAGNOSE +#include <osl/diagnose.h> +#include <rtl/ustrbuf.hxx> +#include <rtl/ustring.hxx> +#include <rtl/string.hxx> +#endif + + +namespace stoc_sec +{ + +/** Implementation of a least recently used (lru) cache. +*/ +template< typename t_key, typename t_val, typename t_hashKey, typename t_equalKey > +class lru_cache +{ + struct Entry + { + t_key m_key; + t_val m_val; + Entry * m_pred; + Entry * m_succ; + }; + typedef ::std::hash_map< t_key, Entry *, t_hashKey, t_equalKey > t_key2element; + t_key2element m_key2element; + ::std::size_t m_size; + + Entry * m_block; + mutable Entry * m_head; + mutable Entry * m_tail; + inline void toFront( Entry * entry ) const SAL_THROW( () ); + +public: + /** Default Ctor. Does not cache. + */ + inline lru_cache() SAL_THROW( () ); + /** Ctor. + + @param size number of elements to be cached; default param set to 128 + */ + inline lru_cache( ::std::size_t size ) SAL_THROW( () ); + + /** Destructor: releases all cached elements and keys. + */ + inline ~lru_cache() SAL_THROW( () ); + + /** Retrieves a pointer to value in cache. Returns 0, if none was found. + + @param key a key + @return pointer to value or 0 + */ + inline t_val const * lookup( t_key const & key ) const SAL_THROW( () ); + + /** Sets a value to be cached for given key. + + @param key a key + @param val a value + */ + inline void set( t_key const & key, t_val const & val ) SAL_THROW( () ); + + /** Tests whether a value is cached for given key. + + @param key a key + @return true, if value is cached + */ + inline bool has( t_key const & key ) const SAL_THROW( () ); + + /** Clears the cache, releasing all cached elements and keys. + */ + inline void clear() SAL_THROW( () ); + + /** Sets the number of elements to be cached. This will clear previous entries. + + @param cacheSize number of elements to be cached + */ + inline void setSize( ::std::size_t size ) SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +template< typename t_key, typename t_val, typename t_hashKey, typename t_equalKey > +inline void lru_cache< t_key, t_val, t_hashKey, t_equalKey >::setSize( + ::std::size_t size ) SAL_THROW( () ) +{ + m_key2element.clear(); + delete [] m_block; + m_block = 0; + m_size = size; + + if (0 < m_size) + { + m_block = new Entry[ m_size ]; + m_head = m_block; + m_tail = m_block + m_size -1; + for ( ::std::size_t nPos = m_size; nPos--; ) + { + m_block[ nPos ].m_pred = m_block + nPos -1; + m_block[ nPos ].m_succ = m_block + nPos +1; + } + } +} +//__________________________________________________________________________________________________ +template< typename t_key, typename t_val, typename t_hashKey, typename t_equalKey > +inline lru_cache< t_key, t_val, t_hashKey, t_equalKey >::lru_cache( + ::std::size_t size ) SAL_THROW( () ) + : m_size( 0 ) + , m_block( 0 ) +{ + setSize( size ); +} +//__________________________________________________________________________________________________ +template< typename t_key, typename t_val, typename t_hashKey, typename t_equalKey > +inline lru_cache< t_key, t_val, t_hashKey, t_equalKey >::lru_cache() SAL_THROW( () ) + : m_size( 0 ) + , m_block( 0 ) +{ +} +//__________________________________________________________________________________________________ +template< typename t_key, typename t_val, typename t_hashKey, typename t_equalKey > +inline lru_cache< t_key, t_val, t_hashKey, t_equalKey >::~lru_cache() + SAL_THROW( () ) +{ + delete [] m_block; +} +//__________________________________________________________________________________________________ +template< typename t_key, typename t_val, typename t_hashKey, typename t_equalKey > +inline void lru_cache< t_key, t_val, t_hashKey, t_equalKey >::toFront( + Entry * entry ) const SAL_THROW( () ) +{ + if (entry != m_head) + { + // cut out element + if (entry == m_tail) + { + m_tail = entry->m_pred; + } + else + { + entry->m_succ->m_pred = entry->m_pred; + entry->m_pred->m_succ = entry->m_succ; + } + // push to front + m_head->m_pred = entry; + entry->m_succ = m_head; + m_head = entry; + } +} +//__________________________________________________________________________________________________ +template< typename t_key, typename t_val, typename t_hashKey, typename t_equalKey > +inline bool lru_cache< t_key, t_val, t_hashKey, t_equalKey >::has( + t_key const & key ) const SAL_THROW( () ) +{ + typename t_key2element::const_iterator const iFind( m_key2element.find( key ) ); + return (iFind != m_key2element.end()); +} +//__________________________________________________________________________________________________ +template< typename t_key, typename t_val, typename t_hashKey, typename t_equalKey > +inline t_val const * lru_cache< t_key, t_val, t_hashKey, t_equalKey >::lookup( + t_key const & key ) const SAL_THROW( () ) +{ + if (0 < m_size) + { + typename t_key2element::const_iterator const iFind( m_key2element.find( key ) ); + if (iFind != m_key2element.end()) + { + Entry * entry = iFind->second; + toFront( entry ); +#ifdef __CACHE_DIAGNOSE + ::rtl::OUStringBuffer buf( 48 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("> retrieved element \"") ); + buf.append( entry->m_key ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" from cache") ); + ::rtl::OString str( ::rtl::OUStringToOString( + buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( str.getStr() ); +#endif + return &entry->m_val; + } + } + return 0; +} +//__________________________________________________________________________________________________ +template< typename t_key, typename t_val, typename t_hashKey, typename t_equalKey > +inline void lru_cache< t_key, t_val, t_hashKey, t_equalKey >::set( + t_key const & key, t_val const & val ) SAL_THROW( () ) +{ + if (0 < m_size) + { + typename t_key2element::const_iterator const iFind( m_key2element.find( key ) ); + + Entry * entry; + if (iFind == m_key2element.end()) + { + entry = m_tail; // erase last element +#ifdef __CACHE_DIAGNOSE + if (entry->m_key.getLength()) + { + ::rtl::OUStringBuffer buf( 48 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("> kicking element \"") ); + buf.append( entry->m_key ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" from cache") ); + ::rtl::OString str( ::rtl::OUStringToOString( + buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( str.getStr() ); + } +#endif + m_key2element.erase( entry->m_key ); + entry->m_key = key; + ::std::pair< typename t_key2element::iterator, bool > insertion( + m_key2element.insert( typename t_key2element::value_type( key, entry ) ) ); +#ifdef __CACHE_DIAGNOSE + OSL_ENSURE( insertion.second, "### inserting new cache entry failed?!" ); +#endif + } + else + { + entry = iFind->second; +#ifdef __CACHE_DIAGNOSE + ::rtl::OUStringBuffer buf( 48 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("> replacing element \"") ); + buf.append( entry->m_key ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" in cache") ); + ::rtl::OString str( ::rtl::OUStringToOString( + buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( str.getStr() ); +#endif + } + entry->m_val = val; + toFront( entry ); + } +} +//__________________________________________________________________________________________________ +template< typename t_key, typename t_val, typename t_hashKey, typename t_equalKey > +inline void lru_cache< t_key, t_val, t_hashKey, t_equalKey >::clear() SAL_THROW( () ) +{ + m_key2element.clear(); + for ( ::std::size_t nPos = m_size; nPos--; ) + { + m_block[ nPos ].m_key = t_key(); + m_block[ nPos ].m_val = t_val(); + } +#ifdef __CACHE_DIAGNOSE + OSL_TRACE( "> cleared cache\n" ); +#endif +} + +} + +#endif diff --git a/stoc/source/security/makefile.mk b/stoc/source/security/makefile.mk new file mode 100644 index 000000000000..25cddaa22539 --- /dev/null +++ b/stoc/source/security/makefile.mk @@ -0,0 +1,62 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME=stoc +TARGET = security +ENABLE_EXCEPTIONS=TRUE +BOOTSTRAP_SERVICE=TRUE +UNOUCROUT=$(OUT)$/inc$/bootstrap + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# ------------------------------------------------------------------ + +SLOFILES= \ + $(SLO)$/permissions.obj \ + $(SLO)$/access_controller.obj \ + $(SLO)$/file_policy.obj + +.IF "$(debug)" != "" + +# some diagnose +.IF "$(diag)" == "full" +CFLAGS += -D__DIAGNOSE -D__CACHE_DIAGNOSE +.ELIF "$(diag)" == "cache" +CFLAGS += -D__CACHE_DIAGNOSE +.ELIF "$(diag)" != "" +CFLAGS += -D__DIAGNOSE +.ENDIF + +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/stoc/source/security/permissions.cxx b/stoc/source/security/permissions.cxx new file mode 100644 index 000000000000..f889725986b7 --- /dev/null +++ b/stoc/source/security/permissions.cxx @@ -0,0 +1,666 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include <vector> + +#include <osl/process.h> +#include <osl/socket.hxx> +#include <osl/mutex.hxx> + +#include <rtl/string.hxx> +#include <rtl/ustrbuf.hxx> + +#include <com/sun/star/security/RuntimePermission.hpp> +#include <com/sun/star/security/AllPermission.hpp> +#include <com/sun/star/io/FilePermission.hpp> +#include <com/sun/star/connection/SocketPermission.hpp> +#include <com/sun/star/security/AccessControlException.hpp> + +#include "permissions.h" + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + + +using namespace ::std; +using namespace ::osl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + +namespace stoc_sec +{ + +//-------------------------------------------------------------------------------------------------- +static inline sal_Int32 makeMask( + OUString const & items, char const * const * strings ) SAL_THROW( () ) +{ + sal_Int32 mask = 0; + + sal_Int32 n = 0; + do + { + OUString item( items.getToken( 0, ',', n ).trim() ); + if (! item.getLength()) + continue; + sal_Int32 nPos = 0; + while (strings[ nPos ]) + { + if (item.equalsAscii( strings[ nPos ] )) + { + mask |= (0x80000000 >> nPos); + break; + } + ++nPos; + } +#if OSL_DEBUG_LEVEL > 0 + if (! strings[ nPos ]) + { + OUStringBuffer buf( 48 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("### ignoring unknown socket action: ") ); + buf.append( item ); + ::rtl::OString str( ::rtl::OUStringToOString( + buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( str.getStr() ); + } +#endif + } + while (n >= 0); // all items + return mask; +} +//-------------------------------------------------------------------------------------------------- +static inline OUString makeStrings( + sal_Int32 mask, char const * const * strings ) SAL_THROW( () ) +{ + OUStringBuffer buf( 48 ); + while (mask) + { + if (0x80000000 & mask) + { + buf.appendAscii( *strings ); + if (mask << 1) // more items following + buf.append( (sal_Unicode)',' ); + } + mask = (mask << 1); + ++strings; + } + return buf.makeStringAndClear(); +} + +//################################################################################################## + +//================================================================================================== +class SocketPermission : public Permission +{ + static char const * s_actions []; + sal_Int32 m_actions; + + OUString m_host; + sal_Int32 m_lowerPort; + sal_Int32 m_upperPort; + mutable OUString m_ip; + mutable bool m_resolveErr; + mutable bool m_resolvedHost; + bool m_wildCardHost; + + inline bool resolveHost() const SAL_THROW( () ); + +public: + SocketPermission( + connection::SocketPermission const & perm, + ::rtl::Reference< Permission > const & next = ::rtl::Reference< Permission >() ) + SAL_THROW( () ); + virtual bool implies( Permission const & perm ) const SAL_THROW( () ); + virtual OUString toString() const SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +char const * SocketPermission::s_actions [] = { "accept", "connect", "listen", "resolve", 0 }; +//__________________________________________________________________________________________________ +SocketPermission::SocketPermission( + connection::SocketPermission const & perm, + ::rtl::Reference< Permission > const & next ) + SAL_THROW( () ) + : Permission( SOCKET, next ) + , m_actions( makeMask( perm.Actions, s_actions ) ) + , m_host( perm.Host ) + , m_lowerPort( 0 ) + , m_upperPort( 65535 ) + , m_resolveErr( false ) + , m_resolvedHost( false ) + , m_wildCardHost( perm.Host.getLength() && '*' == perm.Host.pData->buffer[ 0 ] ) +{ + if (0xe0000000 & m_actions) // if any (except resolve) is given => resolve implied + m_actions |= 0x10000000; + + // separate host from portrange + sal_Int32 colon = m_host.indexOf( ':' ); + if (colon >= 0) // port [range] given + { + sal_Int32 minus = m_host.indexOf( '-', colon +1 ); + if (minus < 0) + { + m_lowerPort = m_upperPort = m_host.copy( colon +1 ).toInt32(); + } + else if (minus == (colon +1)) // -N + { + m_upperPort = m_host.copy( minus +1 ).toInt32(); + } + else if (minus == (m_host.getLength() -1)) // N- + { + m_lowerPort = m_host.copy( colon +1, m_host.getLength() -1 -colon -1 ).toInt32(); + } + else // A-B + { + m_lowerPort = m_host.copy( colon +1, minus - colon -1 ).toInt32(); + m_upperPort = m_host.copy( minus +1, m_host.getLength() -minus -1 ).toInt32(); + } + m_host = m_host.copy( 0, colon ); + } +} +//__________________________________________________________________________________________________ +inline bool SocketPermission::resolveHost() const SAL_THROW( () ) +{ + if (m_resolveErr) + return false; + + if (! m_resolvedHost) + { + // dns lookup + SocketAddr addr; + SocketAddr::resolveHostname( m_host, addr ); + OUString ip; + m_resolveErr = (::osl_Socket_Ok != ::osl_getDottedInetAddrOfSocketAddr( + addr.getHandle(), &ip.pData )); + if (m_resolveErr) + return false; + + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! m_resolvedHost) + { + m_ip = ip; + m_resolvedHost = true; + } + } + return m_resolvedHost; +} +//__________________________________________________________________________________________________ +bool SocketPermission::implies( Permission const & perm ) const SAL_THROW( () ) +{ + // check type + if (SOCKET != perm.m_type) + return false; + SocketPermission const & demanded = static_cast< SocketPermission const & >( perm ); + + // check actions + if ((m_actions & demanded.m_actions) != demanded.m_actions) + return false; + + // check ports + if (demanded.m_lowerPort < m_lowerPort) + return false; + if (demanded.m_upperPort > m_upperPort) + return false; + + // quick check host (DNS names: RFC 1034/1035) + if (m_host.equalsIgnoreAsciiCase( demanded.m_host )) + return true; + // check for host wildcards + if (m_wildCardHost) + { + OUString const & demanded_host = demanded.m_host; + if (demanded_host.getLength() <= m_host.getLength()) + return false; + sal_Int32 len = m_host.getLength() -1; // skip star + return (0 == ::rtl_ustr_compareIgnoreAsciiCase_WithLength( + demanded_host.getStr() + demanded_host.getLength() - len, len, + m_host.pData->buffer + 1, len )); + } + if (demanded.m_wildCardHost) + return false; + + // compare IP addresses + if (! resolveHost()) + return false; + if (! demanded.resolveHost()) + return false; + return (sal_False != m_ip.equals( demanded.m_ip )); +} +//__________________________________________________________________________________________________ +OUString SocketPermission::toString() const SAL_THROW( () ) +{ + OUStringBuffer buf( 48 ); + // host + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("com.sun.star.connection.SocketPermission (host=\"") ); + buf.append( m_host ); + if (m_resolvedHost) + { + buf.append( (sal_Unicode)'[' ); + buf.append( m_ip ); + buf.append( (sal_Unicode)']' ); + } + // port + if (0 != m_lowerPort || 65535 != m_upperPort) + { + buf.append( (sal_Unicode)':' ); + if (m_lowerPort > 0) + buf.append( m_lowerPort ); + if (m_upperPort > m_lowerPort) + { + buf.append( (sal_Unicode)'-' ); + if (m_upperPort < 65535) + buf.append( m_upperPort ); + } + } + // actions + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\", actions=\"") ); + buf.append( makeStrings( m_actions, s_actions ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\")") ); + return buf.makeStringAndClear(); +} + +//################################################################################################## + +//================================================================================================== +class FilePermission : public Permission +{ + static char const * s_actions []; + sal_Int32 m_actions; + + OUString m_url; + bool m_allFiles; + +public: + FilePermission( + io::FilePermission const & perm, + ::rtl::Reference< Permission > const & next = ::rtl::Reference< Permission >() ) + SAL_THROW( () ); + virtual bool implies( Permission const & perm ) const SAL_THROW( () ); + virtual OUString toString() const SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +char const * FilePermission::s_actions [] = { "read", "write", "execute", "delete", 0 }; +//-------------------------------------------------------------------------------------------------- +static OUString const & getWorkingDir() SAL_THROW( () ) +{ + static OUString * s_workingDir = 0; + if (! s_workingDir) + { + OUString workingDir; + ::osl_getProcessWorkingDir( &workingDir.pData ); + + MutexGuard guard( Mutex::getGlobalMutex() ); + if (! s_workingDir) + { + static OUString s_dir( workingDir ); + s_workingDir = &s_dir; + } + } + return *s_workingDir; +} +//__________________________________________________________________________________________________ +FilePermission::FilePermission( + io::FilePermission const & perm, + ::rtl::Reference< Permission > const & next ) + SAL_THROW( () ) + : Permission( FILE, next ) + , m_actions( makeMask( perm.Actions, s_actions ) ) + , m_url( perm.URL ) + , m_allFiles( sal_False != perm.URL.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("<<ALL FILES>>")) ) +{ + if (! m_allFiles) + { + if (m_url.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("*") )) + { + OUStringBuffer buf( 64 ); + buf.append( getWorkingDir() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("/*") ); + m_url = buf.makeStringAndClear(); + } + else if (m_url.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("-") )) + { + OUStringBuffer buf( 64 ); + buf.append( getWorkingDir() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("/-") ); + m_url = buf.makeStringAndClear(); + } + else if (0 != m_url.compareToAscii( RTL_CONSTASCII_STRINGPARAM("file:///") )) + { + // relative path + OUString out; + oslFileError rc = ::osl_getAbsoluteFileURL( + getWorkingDir().pData, perm.URL.pData, &out.pData ); + m_url = (osl_File_E_None == rc ? out : perm.URL); // fallback + } +#ifdef SAL_W32 + // correct win drive letters + if (9 < m_url.getLength() && '|' == m_url[ 9 ]) // file:///X| + { + static OUString s_colon = OUSTR(":"); + // common case in API is a ':' (sal), so convert '|' to ':' + m_url = m_url.replaceAt( 9, 1, s_colon ); + } +#endif + } +} +//__________________________________________________________________________________________________ +bool FilePermission::implies( Permission const & perm ) const SAL_THROW( () ) +{ + // check type + if (FILE != perm.m_type) + return false; + FilePermission const & demanded = static_cast< FilePermission const & >( perm ); + + // check actions + if ((m_actions & demanded.m_actions) != demanded.m_actions) + return false; + + // check url + if (m_allFiles) + return true; + if (demanded.m_allFiles) + return false; + +#ifdef SAL_W32 + if (m_url.equalsIgnoreAsciiCase( demanded.m_url )) + return true; +#else + if (m_url.equals( demanded.m_url )) + return true; +#endif + if (m_url.getLength() > demanded.m_url.getLength()) + return false; + // check /- wildcard: all files and recursive in that path + if (1 < m_url.getLength() && + 0 == ::rtl_ustr_ascii_compare_WithLength( m_url.getStr() + m_url.getLength() - 2, 2, "/-" )) + { + // demanded url must start with granted path (including path trailing path sep) + sal_Int32 len = m_url.getLength() -1; +#ifdef SAL_W32 + return (0 == ::rtl_ustr_compareIgnoreAsciiCase_WithLength( + demanded.m_url.pData->buffer, len, m_url.pData->buffer, len )); +#else + return (0 == ::rtl_ustr_reverseCompare_WithLength( + demanded.m_url.pData->buffer, len, m_url.pData->buffer, len )); +#endif + } + // check /* wildcard: all files in that path (not recursive!) + if (1 < m_url.getLength() && + 0 == ::rtl_ustr_ascii_compare_WithLength( m_url.getStr() + m_url.getLength() - 2, 2, "/*" )) + { + // demanded url must start with granted path (including path trailing path sep) + sal_Int32 len = m_url.getLength() -1; +#ifdef SAL_W32 + return ((0 == ::rtl_ustr_compareIgnoreAsciiCase_WithLength( + demanded.m_url.pData->buffer, len, m_url.pData->buffer, len )) && + (0 > demanded.m_url.indexOf( '/', len ))); // in addition, no deeper pathes +#else + return ((0 == ::rtl_ustr_reverseCompare_WithLength( + demanded.m_url.pData->buffer, len, m_url.pData->buffer, len )) && + (0 > demanded.m_url.indexOf( '/', len ))); // in addition, no deeper pathes +#endif + } + return false; +} +//__________________________________________________________________________________________________ +OUString FilePermission::toString() const SAL_THROW( () ) +{ + OUStringBuffer buf( 48 ); + // url + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("com.sun.star.io.FilePermission (url=\"") ); + buf.append( m_url ); + // actions + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\", actions=\"") ); + buf.append( makeStrings( m_actions, s_actions ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\")") ); + return buf.makeStringAndClear(); +} + +//################################################################################################## + +//================================================================================================== +class RuntimePermission : public Permission +{ + OUString m_name; + +public: + inline RuntimePermission( + security::RuntimePermission const & perm, + ::rtl::Reference< Permission > const & next = ::rtl::Reference< Permission >() ) + SAL_THROW( () ) + : Permission( RUNTIME, next ) + , m_name( perm.Name ) + {} + virtual bool implies( Permission const & perm ) const SAL_THROW( () ); + virtual OUString toString() const SAL_THROW( () ); +}; +//__________________________________________________________________________________________________ +bool RuntimePermission::implies( Permission const & perm ) const SAL_THROW( () ) +{ + // check type + if (RUNTIME != perm.m_type) + return false; + RuntimePermission const & demanded = static_cast< RuntimePermission const & >( perm ); + + // check name + return (sal_False != m_name.equals( demanded.m_name )); +} +//__________________________________________________________________________________________________ +OUString RuntimePermission::toString() const SAL_THROW( () ) +{ + OUStringBuffer buf( 48 ); + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("com.sun.star.security.RuntimePermission (name=\"") ); + buf.append( m_name ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\")") ); + return buf.makeStringAndClear(); +} + +//################################################################################################## + +//__________________________________________________________________________________________________ +bool AllPermission::implies( Permission const & ) const SAL_THROW( () ) +{ + return true; +} +//__________________________________________________________________________________________________ +OUString AllPermission::toString() const SAL_THROW( () ) +{ + return OUSTR("com.sun.star.security.AllPermission"); +} + +//################################################################################################## + +//__________________________________________________________________________________________________ +PermissionCollection::PermissionCollection( + Sequence< Any > const & permissions, PermissionCollection const & addition ) + SAL_THROW( (RuntimeException) ) + : m_head( addition.m_head ) +{ + Any const * perms = permissions.getConstArray(); + for ( sal_Int32 nPos = permissions.getLength(); nPos--; ) + { + Any const & perm = perms[ nPos ]; + Type const & perm_type = perm.getValueType(); + + // supported permission types + if (perm_type.equals( ::getCppuType( (io::FilePermission const *)0 ) )) + { + m_head = new FilePermission( + *reinterpret_cast< io::FilePermission const * >( perm.pData ), m_head ); + } + else if (perm_type.equals( ::getCppuType( (connection::SocketPermission const *)0 ) )) + { + m_head = new SocketPermission( + *reinterpret_cast< connection::SocketPermission const * >( perm.pData ), m_head ); + } + else if (perm_type.equals( ::getCppuType( (security::RuntimePermission const *)0 ) )) + { + m_head = new RuntimePermission( + *reinterpret_cast< security::RuntimePermission const * >( perm.pData ), m_head ); + } + else if (perm_type.equals( ::getCppuType( (security::AllPermission const *)0 ) )) + { + m_head = new AllPermission( m_head ); + } + else + { + OUStringBuffer buf( 48 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "checking for unsupported permission type: ") ); + buf.append( perm_type.getTypeName() ); + throw RuntimeException( + buf.makeStringAndClear(), Reference< XInterface >() ); + } + } +} +#ifdef __DIAGNOSE +//__________________________________________________________________________________________________ +Sequence< OUString > PermissionCollection::toStrings() const SAL_THROW( () ) +{ + vector< OUString > strings; + strings.reserve( 8 ); + for ( Permission * perm = m_head.get(); perm; perm = perm->m_next.get() ) + { + strings.push_back( perm->toString() ); + } + return Sequence< OUString >( + strings.empty() ? 0 : &strings[ 0 ], strings.size() ); +} +#endif +//__________________________________________________________________________________________________ +inline static bool __implies( + ::rtl::Reference< Permission > const & head, Permission const & demanded ) SAL_THROW( () ) +{ + for ( Permission * perm = head.get(); perm; perm = perm->m_next.get() ) + { + if (perm->implies( demanded )) + return true; + } + return false; +} + +#ifdef __DIAGNOSE +//-------------------------------------------------------------------------------------------------- +static void demanded_diag( + Permission const & perm ) + SAL_THROW( () ) +{ + OUStringBuffer buf( 48 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("demanding ") ); + buf.append( perm.toString() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" => ok.") ); + ::rtl::OString str( + ::rtl::OUStringToOString( buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( str.getStr() ); +} +#endif +//-------------------------------------------------------------------------------------------------- +static void throwAccessControlException( + Permission const & perm, Any const & demanded_perm ) + SAL_THROW( (security::AccessControlException) ) +{ + OUStringBuffer buf( 48 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("access denied: ") ); + buf.append( perm.toString() ); + throw security::AccessControlException( + buf.makeStringAndClear(), Reference< XInterface >(), demanded_perm ); +} +//================================================================================================== +void PermissionCollection::checkPermission( Any const & perm ) const + SAL_THROW( (RuntimeException) ) +{ + Type const & demanded_type = perm.getValueType(); + + // supported permission types + // stack object of SimpleReferenceObject are ok, as long as they are not + // assigned to a ::rtl::Reference<> (=> delete this) + if (demanded_type.equals( ::getCppuType( (io::FilePermission const *)0 ) )) + { + FilePermission demanded( + *reinterpret_cast< io::FilePermission const * >( perm.pData ) ); + if (__implies( m_head, demanded )) + { +#ifdef __DIAGNOSE + demanded_diag( demanded ); +#endif + return; + } + throwAccessControlException( demanded, perm ); + } + else if (demanded_type.equals( ::getCppuType( (connection::SocketPermission const *)0 ) )) + { + SocketPermission demanded( + *reinterpret_cast< connection::SocketPermission const * >( perm.pData ) ); + if (__implies( m_head, demanded )) + { +#ifdef __DIAGNOSE + demanded_diag( demanded ); +#endif + return; + } + throwAccessControlException( demanded, perm ); + } + else if (demanded_type.equals( ::getCppuType( (security::RuntimePermission const *)0 ) )) + { + RuntimePermission demanded( + *reinterpret_cast< security::RuntimePermission const * >( perm.pData ) ); + if (__implies( m_head, demanded )) + { +#ifdef __DIAGNOSE + demanded_diag( demanded ); +#endif + return; + } + throwAccessControlException( demanded, perm ); + } + else if (demanded_type.equals( ::getCppuType( (security::AllPermission const *)0 ) )) + { + AllPermission demanded; + if (__implies( m_head, demanded )) + { +#ifdef __DIAGNOSE + demanded_diag( demanded ); +#endif + return; + } + throwAccessControlException( demanded, perm ); + } + else + { + OUStringBuffer buf( 48 ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("checking for unsupported permission type: ") ); + buf.append( demanded_type.getTypeName() ); + throw RuntimeException( + buf.makeStringAndClear(), Reference< XInterface >() ); + } +} + +} diff --git a/stoc/source/security/permissions.h b/stoc/source/security/permissions.h new file mode 100644 index 000000000000..4599023eb205 --- /dev/null +++ b/stoc/source/security/permissions.h @@ -0,0 +1,102 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _STOC_SEC_PERMISSIONS_H_ +#define _STOC_SEC_PERMISSIONS_H_ + +#include <rtl/unload.h> +#include <rtl/ref.hxx> +#include <rtl/ustring.hxx> +#include <salhelper/simplereferenceobject.hxx> + +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/RuntimeException.hpp> + +extern ::rtl_StandardModuleCount g_moduleCount; + +namespace stoc_sec +{ +//================================================================================================== +class Permission : public ::salhelper::SimpleReferenceObject +{ +public: + ::rtl::Reference< Permission > m_next; + // mode + enum t_type { ALL, RUNTIME, SOCKET, FILE } m_type; + + inline Permission( + t_type type, + ::rtl::Reference< Permission > const & next = ::rtl::Reference< Permission >() ) + SAL_THROW( () ) + : m_next( next ) + , m_type( type ) + {} + + virtual bool implies( Permission const & perm ) const SAL_THROW( () ) = 0; + virtual ::rtl::OUString toString() const SAL_THROW( () ) = 0; +}; +//================================================================================================== +class AllPermission : public Permission +{ +public: + inline AllPermission( + ::rtl::Reference< Permission > const & next = ::rtl::Reference< Permission >() ) + SAL_THROW( () ) + : Permission( ALL, next ) + {} + + virtual bool implies( Permission const & ) const SAL_THROW( () ); + virtual ::rtl::OUString toString() const SAL_THROW( () ); +}; + +//================================================================================================== +class PermissionCollection +{ + ::rtl::Reference< Permission > m_head; +public: + inline PermissionCollection() SAL_THROW( () ) + {} + inline PermissionCollection( PermissionCollection const & collection ) SAL_THROW( () ) + : m_head( collection.m_head ) + {} + inline PermissionCollection( ::rtl::Reference< Permission > const & single ) SAL_THROW( () ) + : m_head( single ) + {} + PermissionCollection( + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > const & permissions, + PermissionCollection const & addition = PermissionCollection() ) + SAL_THROW( (::com::sun::star::uno::RuntimeException) ); +#ifdef __DIAGNOSE + ::com::sun::star::uno::Sequence< ::rtl::OUString > toStrings() const SAL_THROW( () ); +#endif + void checkPermission( ::com::sun::star::uno::Any const & perm ) const + SAL_THROW( (::com::sun::star::uno::RuntimeException) ); +}; + +} + +#endif diff --git a/stoc/source/servicemanager/makefile.mk b/stoc/source/servicemanager/makefile.mk new file mode 100644 index 000000000000..f86c65d5f052 --- /dev/null +++ b/stoc/source/servicemanager/makefile.mk @@ -0,0 +1,47 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME= stoc +TARGET = servicemgr +ENABLE_EXCEPTIONS=TRUE +BOOTSTRAP_SERVICE=TRUE +UNOUCROUT=$(OUT)$/inc$/bootstrap + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# ------------------------------------------------------------------ + +SLOFILES= \ + $(SLO)$/servicemanager.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/stoc/source/servicemanager/servicemanager.cxx b/stoc/source/servicemanager/servicemanager.cxx new file mode 100644 index 000000000000..97eb82b6b997 --- /dev/null +++ b/stoc/source/servicemanager/servicemanager.cxx @@ -0,0 +1,2059 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include <osl/mutex.hxx> +#include <osl/diagnose.h> +#include <rtl/ustrbuf.hxx> + +#include <hash_map> +#include <hash_set> +#include <list> +#include <uno/mapping.hxx> +#include <uno/dispatcher.h> +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/weakref.hxx> +#include <cppuhelper/component.hxx> +#include <cppuhelper/factory.hxx> +#ifndef _CPPUHELPER_IMPLBASE1_HXX +#include <cppuhelper/implbase1.hxx> +#endif +#include <cppuhelper/typeprovider.hxx> +#ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_ +#include <cppuhelper/implementationentry.hxx> +#endif +#include <rtl/unload.h> +#include <cppuhelper/component_context.hxx> +#include <cppuhelper/bootstrap.hxx> +#include <cppuhelper/compbase8.hxx> + + +#include <com/sun/star/lang/XUnoTunnel.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XEventListener.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/registry/XSimpleRegistry.hpp> +#include <com/sun/star/container/XSet.hpp> +#include <com/sun/star/container/XElementAccess.hpp> +#include <com/sun/star/container/XEnumeration.hpp> +#include <com/sun/star/container/XContentEnumerationAccess.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/uno/XUnloadingPreference.hpp> + +#include <bootstrapservices.hxx> + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + + +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace com::sun::star::registry; +using namespace com::sun::star::lang; +using namespace com::sun::star::container; +using namespace cppu; +using namespace osl; +using namespace rtl; +using namespace std; + +rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT; + +namespace stoc_bootstrap +{ +Sequence< OUString > smgr_wrapper_getSupportedServiceNames() +{ + static Sequence < OUString > *pNames = 0; + if( ! pNames ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( !pNames ) + { + static Sequence< OUString > seqNames(1); + seqNames.getArray()[0] = OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lang.MultiServiceFactory") ); + pNames = &seqNames; + } + } + return *pNames; +} + +OUString smgr_wrapper_getImplementationName() +{ + static OUString *pImplName = 0; + if( ! pImplName ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( ! pImplName ) + { + static OUString implName( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.stoc.OServiceManagerWrapper" ) ); + pImplName = &implName; + } + } + return *pImplName; +} + +Sequence< OUString > smgr_getSupportedServiceNames() +{ + static Sequence < OUString > *pNames = 0; + if( ! pNames ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( !pNames ) + { + static Sequence< OUString > seqNames(2); + seqNames.getArray()[0] = OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lang.MultiServiceFactory") ); + seqNames.getArray()[1] = OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lang.ServiceManager") ); + pNames = &seqNames; + } + } + return *pNames; +} + +OUString smgr_getImplementationName() +{ + static OUString *pImplName = 0; + if( ! pImplName ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( ! pImplName ) + { + static OUString implName( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.stoc.OServiceManager" ) ); + pImplName = &implName; + } + } + return *pImplName; +} + +Sequence< OUString > regsmgr_getSupportedServiceNames() +{ + static Sequence < OUString > *pNames = 0; + if( ! pNames ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( !pNames ) + { + static Sequence< OUString > seqNames(2); + seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lang.MultiServiceFactory")); + seqNames.getArray()[1] = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lang.RegistryServiceManager")); + pNames = &seqNames; + } + } + return *pNames; +} + +OUString regsmgr_getImplementationName() +{ + static OUString *pImplName = 0; + if( ! pImplName ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( ! pImplName ) + { + static OUString implName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.stoc.ORegistryServiceManager" ) ); + pImplName = &implName; + } + } + return *pImplName; +} +} + +namespace stoc_smgr +{ +static Sequence< sal_Int8 > smgr_getImplementationId() +{ + static OImplementationId * s_pId = 0; + if (! s_pId) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! s_pId) + { + static OImplementationId s_aId; + s_pId = &s_aId; + } + } + return s_pId->getImplementationId(); +} + + +static Sequence< OUString > retrieveAsciiValueList( + const Reference< XSimpleRegistry > &xReg, const OUString &keyName ) +{ + Reference< XEnumerationAccess > xAccess( xReg, UNO_QUERY ); + Sequence< OUString > seq; + if( xAccess.is() ) + { + Reference< XEnumeration > xEnum = xAccess->createEnumeration(); + while( xEnum.is() && xEnum->hasMoreElements() ) + { + Reference< XSimpleRegistry > xTempReg; + xEnum->nextElement() >>= xTempReg; + if( xTempReg.is() ) + { + Sequence< OUString > seq2 = retrieveAsciiValueList( xTempReg, keyName ); + + if( seq2.getLength() ) + { + sal_Int32 n1Len = seq.getLength(); + sal_Int32 n2Len = seq2.getLength(); + + seq.realloc( n1Len + n2Len ); + const OUString *pSource = seq2.getConstArray(); + OUString *pTarget = seq.getArray(); + for( int i = 0 ; i < n2Len ; i ++ ) + { + pTarget[i+n1Len] = pSource[i]; + } + } + } + } + } + else if( xReg.is () ) + { + try + { + Reference< XRegistryKey > rRootKey = xReg->getRootKey(); + if( rRootKey.is() ) + { + Reference<XRegistryKey > xKey = rRootKey->openKey(keyName); + if( xKey.is() ) + { + seq = xKey->getAsciiListValue(); + } + } + } + catch( InvalidRegistryException & ) + { + } + catch (InvalidValueException &) + { + } + } + return seq; +} + +/***************************************************************************** + Enumeration by ServiceName +*****************************************************************************/ +struct hashRef_Impl +{ + size_t operator()(const Reference<XInterface > & rName) const + { + // query to XInterface. The cast to XInterface* must be the same for the same object + Reference<XInterface > x( Reference<XInterface >::query( rName ) ); + return (size_t)x.get(); + } +}; + +struct equaltoRef_Impl +{ + size_t operator()(const Reference<XInterface > & rName1, const Reference<XInterface > & rName2 ) const + { return rName1 == rName2; } +}; + +typedef hash_set +< + Reference<XInterface >, + hashRef_Impl, + equaltoRef_Impl +> HashSet_Ref; + + +class ServiceEnumeration_Impl : public WeakImplHelper1< XEnumeration > +{ +public: + ServiceEnumeration_Impl( const Sequence< Reference<XInterface > > & rFactories ) + : aFactories( rFactories ) + , nIt( 0 ) + { g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); } + virtual ~ServiceEnumeration_Impl() + { g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); } + + // XEnumeration + sal_Bool SAL_CALL hasMoreElements() + throw(::com::sun::star::uno::RuntimeException); + Any SAL_CALL nextElement() + throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); +private: + Mutex aMutex; + Sequence< Reference<XInterface > > aFactories; + sal_Int32 nIt; +}; + +// XEnumeration +sal_Bool ServiceEnumeration_Impl::hasMoreElements() throw(::com::sun::star::uno::RuntimeException) +{ + MutexGuard aGuard( aMutex ); + return nIt != aFactories.getLength(); +} + +// XEnumeration +Any ServiceEnumeration_Impl::nextElement() + throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ + MutexGuard aGuard( aMutex ); + if( nIt == aFactories.getLength() ) + throw NoSuchElementException(); + + return Any( &aFactories.getConstArray()[nIt++], ::getCppuType( (const Reference<XInterface > *)0 ) ); +} + +//================================================================================================== +class PropertySetInfo_Impl : public WeakImplHelper1< beans::XPropertySetInfo > +{ + Sequence< beans::Property > m_properties; + +public: + inline PropertySetInfo_Impl( Sequence< beans::Property > const & properties ) SAL_THROW( () ) + : m_properties( properties ) + {} + + // XPropertySetInfo impl + virtual Sequence< beans::Property > SAL_CALL getProperties() + throw (RuntimeException); + virtual beans::Property SAL_CALL getPropertyByName( OUString const & name ) + throw (beans::UnknownPropertyException, RuntimeException); + virtual sal_Bool SAL_CALL hasPropertyByName( OUString const & name ) + throw (RuntimeException); +}; +//__________________________________________________________________________________________________ +Sequence< beans::Property > PropertySetInfo_Impl::getProperties() + throw (RuntimeException) +{ + return m_properties; +} +//__________________________________________________________________________________________________ +beans::Property PropertySetInfo_Impl::getPropertyByName( OUString const & name ) + throw (beans::UnknownPropertyException, RuntimeException) +{ + beans::Property const * p = m_properties.getConstArray(); + for ( sal_Int32 nPos = m_properties.getLength(); nPos--; ) + { + if (p[ nPos ].Name.equals( name )) + return p[ nPos ]; + } + throw beans::UnknownPropertyException( + OUSTR("unknown property: ") + name, Reference< XInterface >() ); +} +//__________________________________________________________________________________________________ +sal_Bool PropertySetInfo_Impl::hasPropertyByName( OUString const & name ) + throw (RuntimeException) +{ + beans::Property const * p = m_properties.getConstArray(); + for ( sal_Int32 nPos = m_properties.getLength(); nPos--; ) + { + if (p[ nPos ].Name.equals( name )) + return sal_True; + } + return sal_False; +} + + +/***************************************************************************** + Enumeration by implementation +*****************************************************************************/ +class ImplementationEnumeration_Impl : public WeakImplHelper1< XEnumeration > +{ +public: + ImplementationEnumeration_Impl( const HashSet_Ref & rImplementationMap ) + : aImplementationMap( rImplementationMap ) + , aIt( aImplementationMap.begin() ) + { + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + } + virtual ~ImplementationEnumeration_Impl(); + + // XEnumeration + virtual sal_Bool SAL_CALL hasMoreElements() + throw(::com::sun::star::uno::RuntimeException); + virtual Any SAL_CALL nextElement() + throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + +private: + Mutex aMutex; + HashSet_Ref aImplementationMap; + HashSet_Ref::iterator aIt; + sal_Int32 nNext; + Reference<XInterface > xNext; +}; + +ImplementationEnumeration_Impl::~ImplementationEnumeration_Impl() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +// XEnumeration +sal_Bool ImplementationEnumeration_Impl::hasMoreElements() + throw(::com::sun::star::uno::RuntimeException) +{ + MutexGuard aGuard( aMutex ); + return aIt != aImplementationMap.end(); +} + +// XEnumeration +Any ImplementationEnumeration_Impl::nextElement() + throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ + MutexGuard aGuard( aMutex ); + if( aIt == aImplementationMap.end() ) + throw NoSuchElementException(); + + Any ret( &(*aIt), ::getCppuType( (const Reference<XInterface > *)0 ) ); + ++aIt; + return ret; +} + +/***************************************************************************** + Hash tables +*****************************************************************************/ +struct equalOWString_Impl +{ + sal_Bool operator()(const OUString & s1, const OUString & s2) const + { return s1 == s2; } +}; + +struct hashOWString_Impl +{ + size_t operator()(const OUString & rName) const + { return rName.hashCode(); } +}; + +typedef hash_set +< + OUString, + hashOWString_Impl, + equalOWString_Impl +> HashSet_OWString; + +typedef hash_multimap +< + OUString, + Reference<XInterface >, + hashOWString_Impl, + equalOWString_Impl +> HashMultimap_OWString_Interface; + +typedef hash_map +< + OUString, + Reference<XInterface >, + hashOWString_Impl, + equalOWString_Impl +> HashMap_OWString_Interface; + +/***************************************************************************** + class OServiceManager_Listener +*****************************************************************************/ +class OServiceManager_Listener : public WeakImplHelper1< XEventListener > +{ +private: + WeakReference<XSet > xSMgr; + +public: + OServiceManager_Listener( const Reference<XSet > & rSMgr ) + : xSMgr( rSMgr ) + {} + + // XEventListener + virtual void SAL_CALL disposing(const EventObject & rEvt ) throw(::com::sun::star::uno::RuntimeException); +}; + +void OServiceManager_Listener::disposing(const EventObject & rEvt ) + throw(::com::sun::star::uno::RuntimeException) +{ + Reference<XSet > x( xSMgr ); + if( x.is() ) + { + try + { + x->remove( Any( &rEvt.Source, ::getCppuType( (const Reference<XInterface > *)0 ) ) ); + } + catch( const IllegalArgumentException & ) + { + OSL_ENSURE( sal_False, "IllegalArgumentException catched" ); + } + catch( const NoSuchElementException & ) + { + OSL_ENSURE( sal_False, "NoSuchElementException catched" ); + } + } +} + + +/***************************************************************************** + class OServiceManager +*****************************************************************************/ +struct OServiceManagerMutex +{ + Mutex m_mutex; +}; + +extern "C" void SAL_CALL smgrUnloadingListener(void* id); + +typedef WeakComponentImplHelper8< + lang::XMultiServiceFactory, lang::XMultiComponentFactory, lang::XServiceInfo, + lang::XInitialization, lang::XUnoTunnel, + container::XSet, container::XContentEnumerationAccess, + beans::XPropertySet > t_OServiceManager_impl; + +class OServiceManager + : public OServiceManagerMutex + , public t_OServiceManager_impl +{ +public: + friend void SAL_CALL smgrUnloadingListener(void* id); + + OServiceManager( Reference< XComponentContext > const & xContext ); + virtual ~OServiceManager(); + + // XUnoTunnel + sal_Int64 SAL_CALL getSomething( Sequence< sal_Int8 > const & id ) + throw (RuntimeException); + + // XInitialization + void SAL_CALL initialize( Sequence< Any > const & args ) + throw (Exception); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException); + static OUString getImplementationName_Static() throw(::com::sun::star::uno::RuntimeException) + { return stoc_bootstrap::smgr_getImplementationName(); } + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // XMultiComponentFactory + virtual Reference< XInterface > SAL_CALL createInstanceWithContext( + OUString const & rServiceSpecifier, Reference< XComponentContext > const & xContext ) + throw (Exception, RuntimeException); + virtual Reference< XInterface > SAL_CALL createInstanceWithArgumentsAndContext( + OUString const & rServiceSpecifier, + Sequence< Any > const & rArguments, + Reference< XComponentContext > const & xContext ) + throw (Exception, RuntimeException); +// virtual Sequence< OUString > SAL_CALL getAvailableServiceNames() +// throw (RuntimeException); + + // XMultiServiceFactory + virtual Sequence< OUString > SAL_CALL getAvailableServiceNames() throw(::com::sun::star::uno::RuntimeException); + virtual Reference<XInterface > SAL_CALL createInstance(const OUString &) throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + virtual Reference<XInterface > SAL_CALL createInstanceWithArguments(const OUString &, const Sequence<Any >& Arguments) throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // The same as the getAvailableServiceNames, but only uique names + Sequence< OUString > getUniqueAvailableServiceNames( + HashSet_OWString & aNameSet ); + + // XElementAccess + virtual Type SAL_CALL getElementType() throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasElements() throw(::com::sun::star::uno::RuntimeException); + + // XEnumerationAccess + virtual Reference<XEnumeration > SAL_CALL createEnumeration() throw(::com::sun::star::uno::RuntimeException); + + // XSet + virtual sal_Bool SAL_CALL has( const Any & Element ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL insert( const Any & Element ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL remove( const Any & Element ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException); + + // XContentEnumerationAccess + //Sequence< OUString > getAvailableServiceNames() throw( (Exception) ); + virtual Reference<XEnumeration > SAL_CALL createContentEnumeration(const OUString& aServiceName) throw(::com::sun::star::uno::RuntimeException); + virtual Reference<XEnumeration > SAL_CALL createContentEnumeration( + const OUString& aServiceName, Reference< XComponentContext > const & xContext ) + throw(::com::sun::star::uno::RuntimeException); + + // XComponent + virtual void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException); + + // XPropertySet + Reference<XPropertySetInfo > SAL_CALL getPropertySetInfo() + throw(::com::sun::star::uno::RuntimeException); + void SAL_CALL setPropertyValue(const OUString& PropertyName, const Any& aValue) + throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + Any SAL_CALL getPropertyValue(const OUString& PropertyName) + throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + void SAL_CALL addPropertyChangeListener(const OUString& PropertyName, const Reference<XPropertyChangeListener >& aListener) + throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + void SAL_CALL removePropertyChangeListener(const OUString& PropertyName, const Reference<XPropertyChangeListener >& aListener) + throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + void SAL_CALL addVetoableChangeListener(const OUString& PropertyName, const Reference<XVetoableChangeListener >& aListener) + throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + void SAL_CALL removeVetoableChangeListener(const OUString& PropertyName, const Reference<XVetoableChangeListener >& aListener) + throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + +protected: + inline bool is_disposed() const SAL_THROW( (lang::DisposedException) ); + inline void check_undisposed() const SAL_THROW( (lang::DisposedException) ); + virtual void SAL_CALL disposing(); + + sal_Bool haveFactoryWithThisImplementation(const OUString& aImplName); + + virtual Sequence< Reference< XInterface > > queryServiceFactories( + const OUString& aServiceName, Reference< XComponentContext > const & xContext ); + + Reference< XComponentContext > m_xContext; + + Reference< beans::XPropertySetInfo > m_xPropertyInfo; + + sal_Int32 m_nUnloadingListenerId; + + // Does clean up when the unloading mechanism has been set off. It is called from + // the listener function smgrUnloadingListener. + void onUnloadingNotify(); + // factories which have been loaded and not inserted( by XSet::insert) + // are remembered by this set. Those factories + // are not released on a call to onUnloadingNotify + HashSet_Ref m_SetLoadedFactories; +private: + + Reference<XEventListener > getFactoryListener(); + + + HashMultimap_OWString_Interface m_ServiceMap; + HashSet_Ref m_ImplementationMap; + HashMap_OWString_Interface m_ImplementationNameMap; + Reference<XEventListener > xFactoryListener; + bool m_bInDisposing; +}; + + +//______________________________________________________________________________ +inline bool OServiceManager::is_disposed() const + SAL_THROW( (lang::DisposedException) ) +{ + // ought to be guarded by m_mutex: + return (m_bInDisposing || rBHelper.bDisposed); +} + +//______________________________________________________________________________ +inline void OServiceManager::check_undisposed() const + SAL_THROW( (lang::DisposedException) ) +{ + if (is_disposed()) + { + throw lang::DisposedException( + OUSTR("service manager instance has already been disposed!"), + (OWeakObject *)this ); + } +} + +//################################################################################################## +//################################################################################################## +//################################################################################################## + +class OServiceManagerWrapper : public OServiceManagerMutex, public t_OServiceManager_impl +{ + Reference< XComponentContext > m_xContext; + OServiceManager * m_root; + inline OServiceManager * getRoot() SAL_THROW( (RuntimeException) ) + { + if (! m_root) + { + throw lang::DisposedException( + OUSTR("service manager instance has already been disposed!"), + Reference< XInterface >() ); + } + return m_root; + } + +protected: + virtual void SAL_CALL disposing(); + +public: + OServiceManagerWrapper( + Reference< XComponentContext > const & xContext ) + SAL_THROW( (RuntimeException) ); + virtual ~OServiceManagerWrapper() SAL_THROW( () ); + + // XUnoTunnel + sal_Int64 SAL_CALL getSomething( Sequence< sal_Int8 > const & id ) throw (RuntimeException) + { return getRoot()->getSomething( id ); } + + // XInitialization + void SAL_CALL initialize( Sequence< Any > const & args ) throw (Exception) + { getRoot()->initialize( args ); } + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() throw (RuntimeException) + { return getRoot()->getImplementationName(); } + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw (RuntimeException) + { return getRoot()->supportsService( ServiceName ); } + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw (RuntimeException) + { return getRoot()->getSupportedServiceNames(); } + + // XMultiComponentFactory + virtual Reference< XInterface > SAL_CALL createInstanceWithContext( + OUString const & rServiceSpecifier, Reference< XComponentContext > const & xContext ) + throw (Exception, RuntimeException) + { return getRoot()->createInstanceWithContext( rServiceSpecifier, xContext ); } + virtual Reference< XInterface > SAL_CALL createInstanceWithArgumentsAndContext( + OUString const & rServiceSpecifier, + Sequence< Any > const & rArguments, + Reference< XComponentContext > const & xContext ) + throw (Exception, RuntimeException) + { return getRoot()->createInstanceWithArgumentsAndContext( rServiceSpecifier, rArguments, xContext ); } +// virtual Sequence< OUString > SAL_CALL getAvailableServiceNames() +// throw (RuntimeException); + + // XMultiServiceFactory + virtual Sequence< OUString > SAL_CALL getAvailableServiceNames() throw (RuntimeException) + { return getRoot()->getAvailableServiceNames(); } + virtual Reference<XInterface > SAL_CALL createInstance(const OUString & name) throw (Exception) + { return getRoot()->createInstanceWithContext( name, m_xContext ); } + virtual Reference<XInterface > SAL_CALL createInstanceWithArguments(const OUString & name, const Sequence<Any >& Arguments) throw (Exception) + { return getRoot()->createInstanceWithArgumentsAndContext( name, Arguments, m_xContext ); } + + // XElementAccess + virtual Type SAL_CALL getElementType() throw (RuntimeException) + { return getRoot()->getElementType(); } + virtual sal_Bool SAL_CALL hasElements() throw (RuntimeException) + { return getRoot()->hasElements(); } + + // XEnumerationAccess + virtual Reference<XEnumeration > SAL_CALL createEnumeration() throw (RuntimeException) + { return getRoot()->createEnumeration(); } + + // XSet + virtual sal_Bool SAL_CALL has( const Any & Element ) throw (RuntimeException) + { return getRoot()->has( Element ); } + virtual void SAL_CALL insert( const Any & Element ) throw (lang::IllegalArgumentException, container::ElementExistException, RuntimeException) + { getRoot()->insert( Element ); } + virtual void SAL_CALL remove( const Any & Element ) throw (lang::IllegalArgumentException, container::NoSuchElementException, RuntimeException) + { getRoot()->remove( Element ); } + + // XContentEnumerationAccess + //Sequence< OUString > getAvailableServiceNames() throw( (Exception) ); + virtual Reference<XEnumeration > SAL_CALL createContentEnumeration(const OUString& aServiceName) throw (RuntimeException) + { return getRoot()->createContentEnumeration( aServiceName, m_xContext ); } + + // XPropertySet + Reference<XPropertySetInfo > SAL_CALL getPropertySetInfo() throw (RuntimeException) + { return getRoot()->getPropertySetInfo(); } + + void SAL_CALL setPropertyValue(const OUString& PropertyName, const Any& aValue) + throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, RuntimeException); + Any SAL_CALL getPropertyValue(const OUString& PropertyName) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, RuntimeException); + + void SAL_CALL addPropertyChangeListener(const OUString& PropertyName, const Reference<XPropertyChangeListener >& aListener) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, RuntimeException) + { getRoot()->addPropertyChangeListener( PropertyName, aListener ); } + void SAL_CALL removePropertyChangeListener(const OUString& PropertyName, const Reference<XPropertyChangeListener >& aListener) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, RuntimeException) + { getRoot()->removePropertyChangeListener( PropertyName, aListener ); } + void SAL_CALL addVetoableChangeListener(const OUString& PropertyName, const Reference<XVetoableChangeListener >& aListener) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, RuntimeException) + { getRoot()->addVetoableChangeListener( PropertyName, aListener ); } + void SAL_CALL removeVetoableChangeListener(const OUString& PropertyName, const Reference<XVetoableChangeListener >& aListener) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, RuntimeException) + { getRoot()->removeVetoableChangeListener( PropertyName, aListener ); } +}; +//__________________________________________________________________________________________________ +void SAL_CALL OServiceManagerWrapper::setPropertyValue( + const OUString& PropertyName, const Any& aValue ) + throw (beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, RuntimeException) +{ + if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("DefaultContext") )) + { + Reference< XComponentContext > xContext; + if (aValue >>= xContext) + { + MutexGuard aGuard( m_mutex ); + m_xContext = xContext; + } + else + { + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no XComponentContext given!") ), + (OWeakObject *)this, 1 ); + } + } + else + { + getRoot()->setPropertyValue( PropertyName, aValue ); + } +} +//__________________________________________________________________________________________________ +Any SAL_CALL OServiceManagerWrapper::getPropertyValue( + const OUString& PropertyName ) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, RuntimeException) +{ + if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("DefaultContext") )) + { + MutexGuard aGuard( m_mutex ); + if( m_xContext.is() ) + return makeAny( m_xContext ); + else + return Any(); + } + else + { + return getRoot()->getPropertyValue( PropertyName ); + } +} +//__________________________________________________________________________________________________ +void OServiceManagerWrapper::disposing() +{ + m_xContext.clear(); + + if (m_root) + { +// no m_root->dispose(), because every context disposes its service manager... + m_root->release(); + m_root = 0; + } +} +//__________________________________________________________________________________________________ +OServiceManagerWrapper::~OServiceManagerWrapper() SAL_THROW( () ) +{ + if (m_root) + { + m_root->release(); + m_root = 0; + } + + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} +//__________________________________________________________________________________________________ +OServiceManagerWrapper::OServiceManagerWrapper( + Reference< XComponentContext > const & xContext ) + SAL_THROW( (RuntimeException) ) + : t_OServiceManager_impl( m_mutex ) + , m_xContext( xContext ) + , m_root( 0 ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + + Reference< XUnoTunnel > xTunnel( m_xContext->getServiceManager(), UNO_QUERY ); + OSL_ASSERT( xTunnel.is() ); + if (xTunnel.is()) + { + m_root = reinterpret_cast< OServiceManager * >( + xTunnel->getSomething( smgr_getImplementationId() ) ); + OSL_ASSERT( m_root ); + if (m_root) + { + m_root->acquire(); + } + } + + if (! m_root) + { + throw RuntimeException( + OUString( RTL_CONSTASCII_USTRINGPARAM("can only wrap OServiceManager instances!") ), + Reference< XInterface >() ); + } +} + +//################################################################################################## +//################################################################################################## +//################################################################################################## + +// XUnoTunnel +sal_Int64 OServiceManager::getSomething( Sequence< sal_Int8 > const & id ) + throw (RuntimeException) +{ + check_undisposed(); + if (id == smgr_getImplementationId()) + return reinterpret_cast< sal_Int64 >(this); + else + return 0; +} + +/** + * Create a ServiceManager + */ +OServiceManager::OServiceManager( Reference< XComponentContext > const & xContext ) + : t_OServiceManager_impl( m_mutex ) + , m_xContext( xContext ) + , m_bInDisposing( false ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + m_nUnloadingListenerId= rtl_addUnloadingListener( smgrUnloadingListener, this); +} + +/** + * Destroy the ServiceManager + */ +OServiceManager::~OServiceManager() +{ + if( m_nUnloadingListenerId != 0) + rtl_removeUnloadingListener( m_nUnloadingListenerId ); + + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +// Removes entries in m_ServiceMap, m_ImplementationNameMap and m_ImplementationNameMap +// if those entries have not been inserted through XSet::insert. Therefore the entries +// are compared with the entries in m_SetLoadedFactories. +void OServiceManager::onUnloadingNotify() +{ + MutexGuard aGuard( m_mutex); + + typedef HashSet_Ref::const_iterator CIT_S; + typedef HashMultimap_OWString_Interface::iterator IT_MM; + + CIT_S it_SetEnd= m_SetLoadedFactories.end(); + IT_MM it_end1= m_ServiceMap.end(); + list<IT_MM> listDeleteServiceMap; + typedef list<IT_MM>::const_iterator CIT_DMM; + // find occurences in m_ServiceMap + for(IT_MM it_i1= m_ServiceMap.begin(); it_i1 != it_end1; it_i1++) + { + if( m_SetLoadedFactories.find( it_i1->second) != it_SetEnd) + { + Reference<XUnloadingPreference> xunl( it_i1->second, UNO_QUERY); + if( xunl.is()) + { + if( xunl->releaseOnNotification()) + listDeleteServiceMap.push_front( it_i1); + } + else + listDeleteServiceMap.push_front( it_i1); + } + } + // delete elements from m_ServiceMap + CIT_DMM it_end2= listDeleteServiceMap.end(); + for( CIT_DMM it_i2= listDeleteServiceMap.begin(); it_i2 != it_end2; it_i2++) + m_ServiceMap.erase( *it_i2); + + // find elements in m_ImplementationNameMap + typedef HashMap_OWString_Interface::iterator IT_M; + IT_M it_end3= m_ImplementationNameMap.end(); + list<IT_M> listDeleteImplementationNameMap; + typedef list<IT_M>::const_iterator CIT_DM; + for( IT_M it_i3= m_ImplementationNameMap.begin(); it_i3 != it_end3; it_i3++) + { + if( m_SetLoadedFactories.find( it_i3->second) != it_SetEnd) + { + Reference<XUnloadingPreference> xunl( it_i3->second, UNO_QUERY); + if( xunl.is()) + { + if( xunl->releaseOnNotification()) + listDeleteImplementationNameMap.push_front( it_i3); + } + else + listDeleteImplementationNameMap.push_front( it_i3); + } + } + // delete elements from m_ImplementationNameMap + CIT_DM it_end4= listDeleteImplementationNameMap.end(); + for( CIT_DM it_i4= listDeleteImplementationNameMap.begin(); it_i4 != it_end4; it_i4++) + m_ImplementationNameMap.erase( *it_i4); + + // find elements in m_ImplementationMap + typedef HashSet_Ref::iterator IT_S; + IT_S it_end5= m_ImplementationMap.end(); + list<IT_S> listDeleteImplementationMap; + typedef list<IT_S>::const_iterator CIT_DS; + for( IT_S it_i5= m_ImplementationMap.begin(); it_i5 != it_end5; it_i5++) + { + if( m_SetLoadedFactories.find( *it_i5) != it_SetEnd) + { + Reference<XUnloadingPreference> xunl( *it_i5, UNO_QUERY); + if( xunl.is()) + { + if( xunl->releaseOnNotification()) + listDeleteImplementationMap.push_front( it_i5); + } + else + listDeleteImplementationMap.push_front( it_i5); + } + } + // delete elements from m_ImplementationMap + CIT_DS it_end6= listDeleteImplementationMap.end(); + for( CIT_DS it_i6= listDeleteImplementationMap.begin(); it_i6 != it_end6; it_i6++) + m_ImplementationMap.erase( *it_i6); + + // remove Event listener before the factories are released. + IT_S it_end7= m_SetLoadedFactories.end(); + + Reference<XEventListener> xlistener= getFactoryListener(); + for( IT_S it_i7= m_SetLoadedFactories.begin(); it_i7 != it_end7; it_i7++) + { + Reference<XComponent> xcomp( *it_i7, UNO_QUERY); + if( xcomp.is()) + xcomp->removeEventListener( xlistener); + } + // release the factories in m_SetLoadedFactories + m_SetLoadedFactories.clear(); +} + +// XComponent +void OServiceManager::dispose() + throw(::com::sun::star::uno::RuntimeException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + return; + t_OServiceManager_impl::dispose(); +} + +void OServiceManager::disposing() +{ + // dispose all factories + HashSet_Ref aImpls; + { + MutexGuard aGuard( m_mutex ); + m_bInDisposing = true; + aImpls = m_ImplementationMap; + } + HashSet_Ref::iterator aIt = aImpls.begin(); + while( aIt != aImpls.end() ) + { + try + { + Reference<XComponent > xComp( Reference<XComponent >::query( *aIt++ ) ); + if( xComp.is() ) + xComp->dispose(); + } + catch (RuntimeException & exc) + { +#if OSL_DEBUG_LEVEL > 1 + OString str( OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( "### RuntimeException occured upon disposing factory: %s", str.getStr() ); +#else + (void) exc; // unused +#endif + } + } + + // dispose + HashSet_Ref aImplMap; + { + MutexGuard aGuard( m_mutex ); + // erase all members + m_ServiceMap = HashMultimap_OWString_Interface(); + aImplMap = m_ImplementationMap; + m_ImplementationMap = HashSet_Ref(); + m_ImplementationNameMap = HashMap_OWString_Interface(); + m_SetLoadedFactories= HashSet_Ref(); + } + + m_xContext.clear(); + + // not only the Event should hold the object + OSL_ASSERT( m_refCount != 1 ); + + // Revoke this service manager as unloading listener + rtl_removeUnloadingListener( m_nUnloadingListenerId); + m_nUnloadingListenerId=0; +} + +// XPropertySet +Reference<XPropertySetInfo > OServiceManager::getPropertySetInfo() + throw(::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + if (! m_xPropertyInfo.is()) + { + Sequence< beans::Property > seq( 1 ); + seq[ 0 ] = beans::Property( + OUSTR("DefaultContext"), -1, ::getCppuType( &m_xContext ), 0 ); + Reference< beans::XPropertySetInfo > xInfo( new PropertySetInfo_Impl( seq ) ); + + MutexGuard aGuard( m_mutex ); + if (! m_xPropertyInfo.is()) + { + m_xPropertyInfo = xInfo; + } + } + return m_xPropertyInfo; +} + +void OServiceManager::setPropertyValue( + const OUString& PropertyName, const Any& aValue ) + throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("DefaultContext") )) + { + Reference< XComponentContext > xContext; + if (aValue >>= xContext) + { + MutexGuard aGuard( m_mutex ); + m_xContext = xContext; + } + else + { + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no XComponentContext given!") ), + (OWeakObject *)this, 1 ); + } + } + else + { + throw UnknownPropertyException( + OUString( RTL_CONSTASCII_USTRINGPARAM("unknown property ") ) + PropertyName, + (OWeakObject *)this ); + } +} + +Any OServiceManager::getPropertyValue(const OUString& PropertyName) + throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("DefaultContext") )) + { + MutexGuard aGuard( m_mutex ); + if( m_xContext.is() ) + return makeAny( m_xContext ); + else + return Any(); + } + else + { + UnknownPropertyException except; + except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "ServiceManager : unknown property " ) ); + except.Message += PropertyName; + throw except; + } +} + +void OServiceManager::addPropertyChangeListener( + const OUString&, const Reference<XPropertyChangeListener >&) + throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + throw UnknownPropertyException(); +} + +void OServiceManager::removePropertyChangeListener( + const OUString&, const Reference<XPropertyChangeListener >&) + throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + throw UnknownPropertyException(); +} + +void OServiceManager::addVetoableChangeListener( + const OUString&, const Reference<XVetoableChangeListener >&) + throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + throw UnknownPropertyException(); +} + +void OServiceManager::removeVetoableChangeListener( + const OUString&, const Reference<XVetoableChangeListener >&) + throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + throw UnknownPropertyException(); +} + +// OServiceManager +Reference<XEventListener > OServiceManager::getFactoryListener() +{ + check_undisposed(); + MutexGuard aGuard( m_mutex ); + if( !xFactoryListener.is() ) + xFactoryListener = new OServiceManager_Listener( this ); + return xFactoryListener; +} + +// XMultiServiceFactory, XContentEnumeration +Sequence< OUString > OServiceManager::getUniqueAvailableServiceNames( + HashSet_OWString & aNameSet ) +{ + check_undisposed(); + MutexGuard aGuard( m_mutex ); + HashMultimap_OWString_Interface::iterator aSIt = m_ServiceMap.begin(); + while( aSIt != m_ServiceMap.end() ) + aNameSet.insert( (*aSIt++).first ); + + /* do not return the implementation names + HashMap_OWString_Interface m_ImplementationNameMap; + HashMap_OWString_Interface::iterator aIt = m_ImplementationNameMap.begin(); + while( aIt != m_ImplementationNameMap.end() ) + aNameSet.insert( (*aIt++).first ); + */ + + Sequence< OUString > aNames( aNameSet.size() ); + OUString * pArray = aNames.getArray(); + sal_Int32 i = 0; + HashSet_OWString::iterator next = aNameSet.begin(); + while( next != aNameSet.end() ) + pArray[i++] = (*next++); + + return aNames; +} + +// XMultiComponentFactory +Reference< XInterface > OServiceManager::createInstanceWithContext( + OUString const & rServiceSpecifier, + Reference< XComponentContext > const & xContext ) + throw (Exception, RuntimeException) +{ + check_undisposed(); +#if OSL_DEBUG_LEVEL > 0 + Reference< beans::XPropertySet > xProps( xContext->getServiceManager(), UNO_QUERY ); + OSL_ASSERT( xProps.is() ); + if (xProps.is()) + { + Reference< XComponentContext > xDefContext; + xProps->getPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xDefContext; + OSL_ENSURE( + xContext == xDefContext, + "### default context of service manager singleton differs from context holding it!" ); + } +#endif + + Sequence< Reference< XInterface > > factories( + queryServiceFactories( rServiceSpecifier, xContext ) ); + Reference< XInterface > const * p = factories.getConstArray(); + for ( sal_Int32 nPos = 0; nPos < factories.getLength(); ++nPos ) + { + try + { + Reference< XInterface > const & xFactory = p[ nPos ]; + if (xFactory.is()) + { + Reference< XSingleComponentFactory > xFac( xFactory, UNO_QUERY ); + if (xFac.is()) + { + return xFac->createInstanceWithContext( xContext ); + } + else + { + Reference< XSingleServiceFactory > xFac2( xFactory, UNO_QUERY ); + if (xFac2.is()) + { +#if OSL_DEBUG_LEVEL > 1 + OString aStr( OUStringToOString( rServiceSpecifier, RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( "### ignoring given context raising service %s !!!\n", aStr.getStr() ); +#endif + return xFac2->createInstance(); + } + } + } + } + catch (lang::DisposedException & exc) + { +#if OSL_DEBUG_LEVEL > 1 + OString str( OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( "### DisposedException occured: %s", str.getStr() ); +#else + (void) exc; // unused +#endif + } + } + + return Reference< XInterface >(); +} +// XMultiComponentFactory +Reference< XInterface > OServiceManager::createInstanceWithArgumentsAndContext( + OUString const & rServiceSpecifier, + Sequence< Any > const & rArguments, + Reference< XComponentContext > const & xContext ) + throw (Exception, RuntimeException) +{ + check_undisposed(); +#if OSL_DEBUG_LEVEL > 0 + Reference< beans::XPropertySet > xProps( xContext->getServiceManager(), UNO_QUERY ); + OSL_ASSERT( xProps.is() ); + if (xProps.is()) + { + Reference< XComponentContext > xDefContext; + xProps->getPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xDefContext; + OSL_ENSURE( + xContext == xDefContext, + "### default context of service manager singleton differs from context holding it!" ); + } +#endif + + Sequence< Reference< XInterface > > factories( + queryServiceFactories( rServiceSpecifier, xContext ) ); + Reference< XInterface > const * p = factories.getConstArray(); + for ( sal_Int32 nPos = 0; nPos < factories.getLength(); ++nPos ) + { + try + { + Reference< XInterface > const & xFactory = p[ nPos ]; + if (xFactory.is()) + { + Reference< XSingleComponentFactory > xFac( xFactory, UNO_QUERY ); + if (xFac.is()) + { + return xFac->createInstanceWithArgumentsAndContext( rArguments, xContext ); + } + else + { + Reference< XSingleServiceFactory > xFac2( xFactory, UNO_QUERY ); + if (xFac2.is()) + { +#if OSL_DEBUG_LEVEL > 1 + OString aStr( OUStringToOString( rServiceSpecifier, RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( "### ignoring given context raising service %s !!!\n", aStr.getStr() ); +#endif + return xFac2->createInstanceWithArguments( rArguments ); + } + } + } + } + catch (lang::DisposedException & exc) + { +#if OSL_DEBUG_LEVEL > 1 + OString str( OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( "### DisposedException occured: %s", str.getStr() ); +#else + (void) exc; // unused +#endif + } + } + + return Reference< XInterface >(); +} + +// XMultiServiceFactory, XMultiComponentFactory, XContentEnumeration +Sequence< OUString > OServiceManager::getAvailableServiceNames() + throw(::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + // all names + HashSet_OWString aNameSet; + return getUniqueAvailableServiceNames( aNameSet ); +} + +// XMultibleServiceFactory +Reference<XInterface > OServiceManager::createInstance( + const OUString& rServiceSpecifier ) + throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + return createInstanceWithContext( + rServiceSpecifier, m_xContext ); +} + +// XMultibleServiceFactory +Reference<XInterface > OServiceManager::createInstanceWithArguments( + const OUString& rServiceSpecifier, + const Sequence<Any >& rArguments ) + throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + return createInstanceWithArgumentsAndContext( + rServiceSpecifier, rArguments, m_xContext ); +} + +// XInitialization +void OServiceManager::initialize( Sequence< Any > const & ) + throw (Exception) +{ + check_undisposed(); + OSL_ENSURE( 0, "not impl!" ); +} + +// XServiceInfo +OUString OServiceManager::getImplementationName() + throw(::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + return getImplementationName_Static(); +} + +// XServiceInfo +sal_Bool OServiceManager::supportsService(const OUString& ServiceName) + throw(::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + Sequence< OUString > aSNL = getSupportedServiceNames(); + const OUString * pArray = aSNL.getConstArray(); + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return sal_True; + return sal_False; +} + +// XServiceInfo +Sequence< OUString > OServiceManager::getSupportedServiceNames() + throw(::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + return stoc_bootstrap::smgr_getSupportedServiceNames(); +} + + +Sequence< Reference< XInterface > > OServiceManager::queryServiceFactories( + const OUString& aServiceName, Reference< XComponentContext > const & ) +{ + Sequence< Reference< XInterface > > ret; + + MutexGuard aGuard( m_mutex ); + ::std::pair< + HashMultimap_OWString_Interface::iterator, + HashMultimap_OWString_Interface::iterator> p( + m_ServiceMap.equal_range( aServiceName ) ); + + if (p.first == p.second) // no factories + { + // no service found, look for an implementation + HashMap_OWString_Interface::iterator aIt = m_ImplementationNameMap.find( aServiceName ); + if( aIt != m_ImplementationNameMap.end() ) + { + Reference< XInterface > const & x = aIt->second; + // an implementation found + ret = Sequence< Reference< XInterface > >( &x, 1 ); + } + } + else + { + ::std::vector< Reference< XInterface > > vec; + vec.reserve( 4 ); + while (p.first != p.second) + { + vec.push_back( p.first->second ); + ++p.first; + } + ret = Sequence< Reference< XInterface > >( + vec.empty() ? 0 : &vec[ 0 ], vec.size() ); + } + + return ret; +} + +// XContentEnumerationAccess +Reference<XEnumeration > OServiceManager::createContentEnumeration( + const OUString& aServiceName, Reference< XComponentContext > const & xContext ) + throw(::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + Sequence< Reference< XInterface > > factories( + OServiceManager::queryServiceFactories( aServiceName, xContext ) ); + if (factories.getLength()) + return new ServiceEnumeration_Impl( factories ); + else + return Reference< XEnumeration >(); +} +Reference<XEnumeration > OServiceManager::createContentEnumeration( + const OUString& aServiceName ) + throw(::com::sun::star::uno::RuntimeException) +{ + return createContentEnumeration( aServiceName, m_xContext ); +} + +// XEnumeration +Reference<XEnumeration > OServiceManager::createEnumeration() throw(::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + MutexGuard aGuard( m_mutex ); + return new ImplementationEnumeration_Impl( m_ImplementationMap ); +} + +// XElementAccess +Type OServiceManager::getElementType() + throw(::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + return ::getCppuType( (const Reference< XInterface > *)0 ); +} + +// XElementAccess +sal_Bool OServiceManager::hasElements() + throw(::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + MutexGuard aGuard( m_mutex ); + return !m_ImplementationMap.empty(); +} + +// XSet +sal_Bool OServiceManager::has( const Any & Element ) + throw(::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + if( Element.getValueTypeClass() == TypeClass_INTERFACE ) + { + Reference<XInterface > xEle( Element, UNO_QUERY_THROW ); + MutexGuard aGuard( m_mutex ); + return m_ImplementationMap.find( xEle ) != + m_ImplementationMap.end(); + } + else if (Element.getValueTypeClass() == TypeClass_STRING) + { + OUString const & implName = + *reinterpret_cast< OUString const * >(Element.getValue()); + MutexGuard aGuard( m_mutex ); + return m_ImplementationNameMap.find( implName ) != + m_ImplementationNameMap.end(); + } + return sal_False; +} + +// XSet +void OServiceManager::insert( const Any & Element ) + throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + if( Element.getValueTypeClass() != TypeClass_INTERFACE ) + { + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no interface given!") ), + Reference< XInterface >(), 0 ); + } + Reference<XInterface > xEle( Element, UNO_QUERY_THROW ); + + { + MutexGuard aGuard( m_mutex ); + HashSet_Ref::iterator aIt = m_ImplementationMap.find( xEle ); + if( aIt != m_ImplementationMap.end() ) + { + throw ElementExistException( + OUString( RTL_CONSTASCII_USTRINGPARAM("element already exists!") ), + Reference< XInterface >() ); + } + + // put into the implementation hashmap + m_ImplementationMap.insert( xEle ); + + // put into the implementation name hashmap + Reference<XServiceInfo > xInfo( Reference<XServiceInfo >::query( xEle ) ); + if( xInfo.is() ) + { + OUString aImplName = xInfo->getImplementationName(); + if( aImplName.getLength() ) + m_ImplementationNameMap[ aImplName ] = xEle; + + //put into the service map + Sequence< OUString > aServiceNames = xInfo->getSupportedServiceNames(); + const OUString * pArray = aServiceNames.getConstArray(); + for( sal_Int32 i = 0; i < aServiceNames.getLength(); i++ ) + { + m_ServiceMap.insert( HashMultimap_OWString_Interface::value_type( + pArray[i], *(Reference<XInterface > *)Element.getValue() ) ); + } + } + } + // add the disposing listener to the factory + Reference<XComponent > xComp( Reference<XComponent >::query( xEle ) ); + if( xComp.is() ) + xComp->addEventListener( getFactoryListener() ); +} + +// helper function +sal_Bool OServiceManager::haveFactoryWithThisImplementation(const OUString& aImplName) +{ + return ( m_ImplementationNameMap.find(aImplName) != m_ImplementationNameMap.end()); +} + +// XSet +void OServiceManager::remove( const Any & Element ) + throw(::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException) +{ + if (is_disposed()) + return; + + Reference<XInterface > xEle; + if (Element.getValueTypeClass() == TypeClass_INTERFACE) + { + xEle.set( Element, UNO_QUERY_THROW ); + } + else if (Element.getValueTypeClass() == TypeClass_STRING) + { + OUString const & implName = + *reinterpret_cast< OUString const * >(Element.getValue()); + MutexGuard aGuard( m_mutex ); + HashMap_OWString_Interface::const_iterator const iFind( + m_ImplementationNameMap.find( implName ) ); + if (iFind == m_ImplementationNameMap.end()) + { + throw NoSuchElementException( + OUString( RTL_CONSTASCII_USTRINGPARAM("element is not in: ") ) + + implName, static_cast< OWeakObject * >(this) ); + } + xEle = iFind->second; + } + else + { + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM( + "neither interface nor string given!") ), + Reference< XInterface >(), 0 ); + } + + // remove the disposing listener from the factory + Reference<XComponent > xComp( Reference<XComponent >::query( xEle ) ); + if( xComp.is() ) + xComp->removeEventListener( getFactoryListener() ); + + MutexGuard aGuard( m_mutex ); + HashSet_Ref::iterator aIt = m_ImplementationMap.find( xEle ); + if( aIt == m_ImplementationMap.end() ) + { + throw NoSuchElementException( + OUString( RTL_CONSTASCII_USTRINGPARAM("element is not in!") ), + static_cast< OWeakObject * >(this) ); + } + //First remove all factories which have been loaded by ORegistryServiceManager. + m_SetLoadedFactories.erase( *aIt); + //Remove from the implementation map. It contains all factories of m_SetLoadedFactories + //which have been added directly through XSet, that is not via ORegistryServiceManager + m_ImplementationMap.erase( aIt ); + + // remove from the implementation name hashmap + Reference<XServiceInfo > xInfo( Reference<XServiceInfo >::query( xEle ) ); + if( xInfo.is() ) + { + OUString aImplName = xInfo->getImplementationName(); + if( aImplName.getLength() ) + m_ImplementationNameMap.erase( aImplName ); + } + + //remove from the service map + Reference<XServiceInfo > xSF( Reference<XServiceInfo >::query( xEle ) ); + if( xSF.is() ) + { + Sequence< OUString > aServiceNames = xSF->getSupportedServiceNames(); + const OUString * pArray = aServiceNames.getConstArray(); + for( sal_Int32 i = 0; i < aServiceNames.getLength(); i++ ) + { + pair<HashMultimap_OWString_Interface::iterator, HashMultimap_OWString_Interface::iterator> p = + m_ServiceMap.equal_range( pArray[i] ); + + while( p.first != p.second ) + { + if( xEle == (*p.first).second ) + { + m_ServiceMap.erase( p.first ); + break; + } + ++p.first; + } + } + } +} + +/***************************************************************************** + class ORegistryServiceManager +*****************************************************************************/ +class ORegistryServiceManager : public OServiceManager +{ +public: + ORegistryServiceManager( Reference< XComponentContext > const & xContext ); + virtual ~ORegistryServiceManager(); + + // XInitialization + void SAL_CALL initialize(const Sequence< Any >& Arguments) + throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XServiceInfo + OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException) + { return stoc_bootstrap::regsmgr_getImplementationName(); } + + Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // XMultiServiceFactory + Sequence< OUString > SAL_CALL getAvailableServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // XContentEnumerationAccess + //Sequence< OUString > getAvailableServiceNames() throw( (Exception) ); + Reference<XEnumeration > SAL_CALL createContentEnumeration(const OUString& aServiceName) throw(::com::sun::star::uno::RuntimeException); + virtual Reference<XEnumeration > SAL_CALL createContentEnumeration( + const OUString& aServiceName, Reference< XComponentContext > const & xContext ) + throw(::com::sun::star::uno::RuntimeException); + + // XComponent + void SAL_CALL dispose() throw(::com::sun::star::uno::RuntimeException); + + // OServiceManager + Reference<XPropertySetInfo > SAL_CALL getPropertySetInfo() + throw(::com::sun::star::uno::RuntimeException); + Any SAL_CALL getPropertyValue(const OUString& PropertyName) + throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); + +protected: + //OServiceManager + Sequence< Reference< XInterface > > queryServiceFactories( + const OUString& aServiceName, Reference< XComponentContext > const & xContext ); +private: + Reference<XRegistryKey > getRootKey(); + Reference<XInterface > loadWithImplementationName( + const OUString & rImplName, Reference< XComponentContext > const & xContext ); + Sequence<OUString> getFromServiceName(const OUString& serviceName); + Reference<XInterface > loadWithServiceName( + const OUString & rImplName, Reference< XComponentContext > const & xContext ); + void fillAllNamesFromRegistry( HashSet_OWString & ); + + sal_Bool m_searchedRegistry; + Reference<XSimpleRegistry > m_xRegistry; // readonly property Registry + Reference<XRegistryKey > m_xRootKey; + +#if OSL_DEBUG_LEVEL > 0 + bool m_init; +#endif +}; + +/** + * Create a ServiceManager + */ +ORegistryServiceManager::ORegistryServiceManager( Reference< XComponentContext > const & xContext ) + : OServiceManager( xContext ) + , m_searchedRegistry(sal_False) +#if OSL_DEBUG_LEVEL > 0 + , m_init( false ) +#endif +{ +} + +/** + * Destroy the ServiceManager + */ +ORegistryServiceManager::~ORegistryServiceManager() +{ +} + +// XComponent +void ORegistryServiceManager::dispose() + throw(::com::sun::star::uno::RuntimeException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + return; + OServiceManager::dispose(); + // dispose + MutexGuard aGuard( m_mutex ); + // erase all members + m_xRegistry = Reference<XSimpleRegistry >(); + m_xRootKey = Reference<XRegistryKey >(); +} + +/** + * Return the root key of the registry. The Default registry service is ordered + * if no registry is set. + */ +//Reference<XServiceProvider > create_DefaultRegistry_ServiceProvider(); + +Reference<XRegistryKey > ORegistryServiceManager::getRootKey() +{ + if( !m_xRootKey.is() ) + { + MutexGuard aGuard( m_mutex ); + // DefaultRegistry suchen !!!! + if( !m_xRegistry.is() && !m_searchedRegistry ) + { + // merken, es wird nur einmal gesucht + m_searchedRegistry = sal_True; + + m_xRegistry.set( + createInstanceWithContext( + OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.registry.DefaultRegistry") ), + m_xContext ), + UNO_QUERY ); + } + if( m_xRegistry.is() && !m_xRootKey.is() ) + m_xRootKey = m_xRegistry->getRootKey(); + } + + return m_xRootKey; +} + +/** + * Create a service provider from the registry with an implementation name + */ +Reference<XInterface > ORegistryServiceManager::loadWithImplementationName( + const OUString& name, Reference< XComponentContext > const & xContext ) +{ + Reference<XInterface > ret; + + Reference<XRegistryKey > xRootKey = getRootKey(); + if( !xRootKey.is() ) + return ret; + + try + { + OUString implementationName = OUString( RTL_CONSTASCII_USTRINGPARAM("/IMPLEMENTATIONS/") ) + name; + Reference<XRegistryKey > xImpKey = m_xRootKey->openKey(implementationName); + + if( xImpKey.is() ) + { + Reference< lang::XMultiServiceFactory > xMgr; + if (xContext.is()) + xMgr.set( xContext->getServiceManager(), UNO_QUERY_THROW ); + else + xMgr.set( this ); + ret = createSingleRegistryFactory( xMgr, name, xImpKey ); + insert( makeAny( ret ) ); + // Remember this factory as loaded in contrast to inserted ( XSet::insert) + // factories. Those loaded factories in this set are candidates for being + // released on an unloading notification. + m_SetLoadedFactories.insert( ret); + } + } + catch (InvalidRegistryException &) + { + } + + return ret; +} + +/** + * Return all implementation out of the registry. + */ +Sequence<OUString> ORegistryServiceManager::getFromServiceName( + const OUString& serviceName ) +{ + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "/SERVICES/" ) ); + buf.append( serviceName ); + return retrieveAsciiValueList( m_xRegistry, buf.makeStringAndClear() ); +} + +/** + * Create a service provider from the registry + */ +Reference<XInterface > ORegistryServiceManager::loadWithServiceName( + const OUString& serviceName, Reference< XComponentContext > const & xContext ) +{ + Sequence<OUString> implEntries = getFromServiceName( serviceName ); + for (sal_Int32 i = 0; i < implEntries.getLength(); i++) + { + Reference< XInterface > x( + loadWithImplementationName( implEntries.getConstArray()[i], xContext ) ); + if (x.is()) + return x; + } + + return Reference<XInterface >(); +} + +/** + * Return a sequence of all service names from the registry. + */ +void ORegistryServiceManager::fillAllNamesFromRegistry( HashSet_OWString & rSet ) +{ + Reference<XRegistryKey > xRootKey = getRootKey(); + if( !xRootKey.is() ) + return; + + try + { + Reference<XRegistryKey > xServicesKey = xRootKey->openKey( + OUString( RTL_CONSTASCII_USTRINGPARAM("SERVICES") ) ); + // root + /Services + / + if( xServicesKey.is() ) + { + sal_Int32 nPrefix = xServicesKey->getKeyName().getLength() +1; + Sequence<Reference<XRegistryKey > > aKeys = xServicesKey->openKeys(); + for( sal_Int32 i = 0; i < aKeys.getLength(); i++ ) + rSet.insert( aKeys.getConstArray()[i]->getKeyName().copy( nPrefix ) ); + } + } + catch (InvalidRegistryException &) + { + } +} + +// XInitialization +void ORegistryServiceManager::initialize(const Sequence< Any >& Arguments) + throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + MutexGuard aGuard( m_mutex ); + if (Arguments.getLength() > 0) + { + m_xRootKey.clear(); + Arguments[ 0 ] >>= m_xRegistry; + } +#if OSL_DEBUG_LEVEL > 0 + // to find all bootstrapping processes to be fixed... + OSL_ENSURE( !m_init, "### second init of service manager instance!" ); + m_init = true; +#endif +} + +// XMultiServiceFactory, XContentEnumeration +Sequence< OUString > ORegistryServiceManager::getAvailableServiceNames() + throw(::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + MutexGuard aGuard( m_mutex ); + // all names + HashSet_OWString aNameSet; + + // all names from the registry + fillAllNamesFromRegistry( aNameSet ); + + return OServiceManager::getUniqueAvailableServiceNames( aNameSet ); +} + +// XServiceInfo +Sequence< OUString > ORegistryServiceManager::getSupportedServiceNames() + throw(::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + return stoc_bootstrap::regsmgr_getSupportedServiceNames(); +} + + +// OServiceManager +Sequence< Reference< XInterface > > ORegistryServiceManager::queryServiceFactories( + const OUString& aServiceName, Reference< XComponentContext > const & xContext ) +{ + Sequence< Reference< XInterface > > ret( + OServiceManager::queryServiceFactories( aServiceName, xContext ) ); + if (ret.getLength()) + { + return ret; + } + else + { + MutexGuard aGuard( m_mutex ); + Reference< XInterface > x( loadWithServiceName( aServiceName, xContext ) ); + if (! x.is()) + x = loadWithImplementationName( aServiceName, xContext ); + return Sequence< Reference< XInterface > >( &x, 1 ); + } +} + +// XContentEnumerationAccess +Reference<XEnumeration > ORegistryServiceManager::createContentEnumeration( + const OUString& aServiceName, Reference< XComponentContext > const & xContext ) + throw(::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + MutexGuard aGuard( ((ORegistryServiceManager *)this)->m_mutex ); + // get all implementation names registered under this service name from the registry + Sequence<OUString> aImpls = ((ORegistryServiceManager *)this)->getFromServiceName( aServiceName ); + // load and insert all factories specified by the registry + sal_Int32 i; + OUString aImplName; + for( i = 0; i < aImpls.getLength(); i++ ) + { + aImplName = aImpls.getConstArray()[i]; + if ( !haveFactoryWithThisImplementation(aImplName) ) + { + loadWithImplementationName( aImplName, xContext ); + } + } + // call the superclass to enumerate all contents + return OServiceManager::createContentEnumeration( aServiceName, xContext ); +} +Reference<XEnumeration > ORegistryServiceManager::createContentEnumeration( + const OUString& aServiceName ) + throw(::com::sun::star::uno::RuntimeException) +{ + return createContentEnumeration( aServiceName, m_xContext ); +} + +// OServiceManager +Reference<XPropertySetInfo > ORegistryServiceManager::getPropertySetInfo() + throw(::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + if (! m_xPropertyInfo.is()) + { + Sequence< beans::Property > seq( 2 ); + seq[ 0 ] = beans::Property( + OUSTR("DefaultContext"), -1, ::getCppuType( &m_xContext ), 0 ); + seq[ 1 ] = beans::Property( + OUSTR("Registry"), -1, ::getCppuType( &m_xRegistry ), + beans::PropertyAttribute::READONLY ); + Reference< beans::XPropertySetInfo > xInfo( new PropertySetInfo_Impl( seq ) ); + + MutexGuard aGuard( m_mutex ); + if (! m_xPropertyInfo.is()) + { + m_xPropertyInfo = xInfo; + } + } + return m_xPropertyInfo; +} + +Any ORegistryServiceManager::getPropertyValue(const OUString& PropertyName) + throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ + check_undisposed(); + if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Registry") )) + { + MutexGuard aGuard( m_mutex ); + if( m_xRegistry.is() ) + return makeAny( m_xRegistry ); + else + return Any(); + } + return OServiceManager::getPropertyValue( PropertyName ); +} + +/* This is the listener function used by the service manager in order +to implement the unloading mechanism, id is the this pointer of the +service manager instances. On notification, that is the function is being called +by rtl_unloadUnusedModules, the cached factroies are being removed from the +service manager ( except manually inserted factories). +*/ +extern "C" void SAL_CALL smgrUnloadingListener(void* id) +{ + stoc_smgr::OServiceManager* pMgr= reinterpret_cast<stoc_smgr::OServiceManager*>( id); + pMgr->onUnloadingNotify(); +} + +} // namespace + +namespace stoc_bootstrap +{ +/** + * Create the ServiceManager + */ +Reference<XInterface > SAL_CALL OServiceManager_CreateInstance( + const Reference< XComponentContext > & xContext ) +{ + return Reference<XInterface >( + SAL_STATIC_CAST( + XInterface *, SAL_STATIC_CAST( + OWeakObject *, new stoc_smgr::OServiceManager( xContext ) ) ) ); +} + +/** + * Create the ServiceManager + */ +Reference<XInterface > SAL_CALL ORegistryServiceManager_CreateInstance( + const Reference< XComponentContext > & xContext ) + throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException) +{ + return Reference<XInterface >( + SAL_STATIC_CAST( + XInterface *, SAL_STATIC_CAST( + OWeakObject *, new stoc_smgr::ORegistryServiceManager( xContext ) ) ) ); +} + +Reference<XInterface > SAL_CALL OServiceManagerWrapper_CreateInstance( + const Reference< XComponentContext > & xContext ) + throw (Exception) +{ + return (OWeakObject *)new stoc_smgr::OServiceManagerWrapper( xContext ); +} +} diff --git a/stoc/source/simpleregistry/makefile.mk b/stoc/source/simpleregistry/makefile.mk new file mode 100644 index 000000000000..bc0ddf7cc71a --- /dev/null +++ b/stoc/source/simpleregistry/makefile.mk @@ -0,0 +1,47 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME= stoc +TARGET = simplereg +ENABLE_EXCEPTIONS=TRUE +BOOTSTRAP_SERVICE=TRUE +UNOUCROUT=$(OUT)$/inc$/bootstrap + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# ------------------------------------------------------------------ + +SLOFILES= \ + $(SLO)/simpleregistry.obj \ + $(SLO)/textualservices.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/stoc/source/simpleregistry/simpleregistry.cxx b/stoc/source/simpleregistry/simpleregistry.cxx new file mode 100755 index 000000000000..9c6b71bc6c83 --- /dev/null +++ b/stoc/source/simpleregistry/simpleregistry.cxx @@ -0,0 +1,1320 @@ +/************************************************************************* +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +* +************************************************************************/ + +#include "precompiled_stoc.hxx" +#include "sal/config.h" + +#include <cstdlib> +#include <memory> +#include <vector> + +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/registry/InvalidRegistryException.hpp" +#include "com/sun/star/registry/InvalidValueException.hpp" +#include "com/sun/star/registry/MergeConflictException.hpp" +#include "com/sun/star/registry/RegistryKeyType.hpp" +#include "com/sun/star/registry/XRegistryKey.hpp" +#include "com/sun/star/registry/XSimpleRegistry.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/implbase2.hxx" +#include "cppuhelper/weak.hxx" +#include "osl/mutex.hxx" +#include "registry/registry.hxx" +#include "registry/regtype.h" +#include "rtl/ref.hxx" +#include "rtl/string.h" +#include "rtl/string.hxx" +#include "rtl/textcvt.h" +#include "rtl/textenc.h" +#include "rtl/unload.h" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" + +#include "bootstrapservices.hxx" + +#include "textualservices.hxx" + +extern rtl_StandardModuleCount g_moduleCount; + +namespace { + +namespace css = com::sun::star; + +class SimpleRegistry: + public cppu::WeakImplHelper2< + css::registry::XSimpleRegistry, css::lang::XServiceInfo > +{ +public: + SimpleRegistry() { g_moduleCount.modCnt.acquire(&g_moduleCount.modCnt); } + + ~SimpleRegistry() { g_moduleCount.modCnt.release(&g_moduleCount.modCnt); } + + osl::Mutex mutex_; + +private: + virtual rtl::OUString SAL_CALL getURL() throw (css::uno::RuntimeException); + + virtual void SAL_CALL open( + rtl::OUString const & rURL, sal_Bool bReadOnly, sal_Bool bCreate) + throw ( + css::registry::InvalidRegistryException, + css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isValid() throw (css::uno::RuntimeException); + + virtual void SAL_CALL close() throw ( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual void SAL_CALL destroy() throw( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual css::uno::Reference< css::registry::XRegistryKey > SAL_CALL + getRootKey() throw( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isReadOnly() throw( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual void SAL_CALL mergeKey( + rtl::OUString const & aKeyName, rtl::OUString const & aUrl) + throw ( + css::registry::InvalidRegistryException, + css::registry::MergeConflictException, css::uno::RuntimeException); + + virtual rtl::OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException) + { return stoc_bootstrap::simreg_getImplementationName(); } + + virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & ServiceName) + throw (css::uno::RuntimeException) + { return ServiceName == getSupportedServiceNames()[0]; } + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames() throw (css::uno::RuntimeException) + { return stoc_bootstrap::simreg_getSupportedServiceNames(); } + + Registry registry_; + std::auto_ptr< stoc::simpleregistry::TextualServices > textual_; +}; + +class Key: public cppu::WeakImplHelper1< css::registry::XRegistryKey > { +public: + Key( + rtl::Reference< SimpleRegistry > const & registry, + RegistryKey const & key): + registry_(registry), key_(key) {} + +private: + virtual rtl::OUString SAL_CALL getKeyName() + throw (css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isReadOnly() throw ( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isValid() throw(css::uno::RuntimeException); + + virtual css::registry::RegistryKeyType SAL_CALL getKeyType( + rtl::OUString const & rKeyName) + throw ( + css::registry::InvalidRegistryException, + css::uno::RuntimeException); + + virtual css::registry::RegistryValueType SAL_CALL getValueType() throw( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getLongValue() throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException); + + virtual void SAL_CALL setLongValue(sal_Int32 value) throw ( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual css::uno::Sequence< sal_Int32 > SAL_CALL getLongListValue() throw( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException); + + virtual void SAL_CALL setLongListValue( + com::sun::star::uno::Sequence< sal_Int32 > const & seqValue) + throw ( + css::registry::InvalidRegistryException, + css::uno::RuntimeException); + + virtual rtl::OUString SAL_CALL getAsciiValue() throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException); + + virtual void SAL_CALL setAsciiValue(rtl::OUString const & value) throw ( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL getAsciiListValue() + throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException); + + virtual void SAL_CALL setAsciiListValue( + css::uno::Sequence< rtl::OUString > const & seqValue) + throw ( + css::registry::InvalidRegistryException, + css::uno::RuntimeException); + + virtual rtl::OUString SAL_CALL getStringValue() throw( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException); + + virtual void SAL_CALL setStringValue(rtl::OUString const & value) throw ( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL getStringListValue() + throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException); + + virtual void SAL_CALL setStringListValue( + css::uno::Sequence< rtl::OUString > const & seqValue) + throw ( + css::registry::InvalidRegistryException, + css::uno::RuntimeException); + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getBinaryValue() throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException); + + virtual void SAL_CALL setBinaryValue( + css::uno::Sequence< sal_Int8 > const & value) + throw ( + css::registry::InvalidRegistryException, + css::uno::RuntimeException); + + virtual css::uno::Reference< css::registry::XRegistryKey > SAL_CALL openKey( + rtl::OUString const & aKeyName) + throw ( + css::registry::InvalidRegistryException, + css::uno::RuntimeException); + + virtual css::uno::Reference< css::registry::XRegistryKey > SAL_CALL + createKey(rtl::OUString const & aKeyName) throw ( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual void SAL_CALL closeKey() throw ( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual void SAL_CALL deleteKey(rtl::OUString const & rKeyName) throw ( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual + css::uno::Sequence< css::uno::Reference< css::registry::XRegistryKey > > + SAL_CALL openKeys() throw ( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL getKeyNames() throw ( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL createLink( + rtl::OUString const & aLinkName, rtl::OUString const & aLinkTarget) + throw ( + css::registry::InvalidRegistryException, + css::uno::RuntimeException); + + virtual void SAL_CALL deleteLink(rtl::OUString const & rLinkName) throw ( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual rtl::OUString SAL_CALL getLinkTarget( + rtl::OUString const & rLinkName) + throw ( + css::registry::InvalidRegistryException, + css::uno::RuntimeException); + + virtual rtl::OUString SAL_CALL getResolvedName( + rtl::OUString const & aKeyName) + throw ( + css::registry::InvalidRegistryException, + css::uno::RuntimeException); + + rtl::Reference< SimpleRegistry > registry_; + RegistryKey key_; +}; + +rtl::OUString Key::getKeyName() throw (css::uno::RuntimeException) { + osl::MutexGuard guard(registry_->mutex_); + return key_.getName(); +} + +sal_Bool Key::isReadOnly() + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + return key_.isReadOnly(); +} + +sal_Bool Key::isValid() throw (css::uno::RuntimeException) { + osl::MutexGuard guard(registry_->mutex_); + return key_.isValid(); +} + +css::registry::RegistryKeyType Key::getKeyType(rtl::OUString const & rKeyName) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + RegKeyType type; + RegError err = key_.getKeyType(rKeyName, &type); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getKeyType:" + " underlying RegistryKey::getKeyType() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } + switch (type) { + default: + std::abort(); // this cannot happen + // pseudo-fall-through to avoid warnings on MSC + case RG_KEYTYPE: + return css::registry::RegistryKeyType_KEY; + case RG_LINKTYPE: + return css::registry::RegistryKeyType_LINK; + } +} + +css::registry::RegistryValueType Key::getValueType() + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + RegValueType type; + sal_uInt32 size; + RegError err = key_.getValueInfo(rtl::OUString(), &type, &size); + switch (err) { + case REG_NO_ERROR: + break; + case REG_INVALID_VALUE: + type = RG_VALUETYPE_NOT_DEFINED; + break; + default: + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getValueType:" + " underlying RegistryKey::getValueInfo() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } + switch (type) { + default: + std::abort(); // this cannot happen + // pseudo-fall-through to avoid warnings on MSC + case RG_VALUETYPE_NOT_DEFINED: + return css::registry::RegistryValueType_NOT_DEFINED; + case RG_VALUETYPE_LONG: + return css::registry::RegistryValueType_LONG; + case RG_VALUETYPE_STRING: + return css::registry::RegistryValueType_ASCII; + case RG_VALUETYPE_UNICODE: + return css::registry::RegistryValueType_STRING; + case RG_VALUETYPE_BINARY: + return css::registry::RegistryValueType_BINARY; + case RG_VALUETYPE_LONGLIST: + return css::registry::RegistryValueType_LONGLIST; + case RG_VALUETYPE_STRINGLIST: + return css::registry::RegistryValueType_ASCIILIST; + case RG_VALUETYPE_UNICODELIST: + return css::registry::RegistryValueType_STRINGLIST; + } +} + +sal_Int32 Key::getLongValue() throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + sal_Int32 value; + RegError err = key_.getValue(rtl::OUString(), &value); + switch (err) { + case REG_NO_ERROR: + break; + case REG_INVALID_VALUE: + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getLongValue:" + " underlying RegistryKey::getValue() = REG_INVALID_VALUE")), + static_cast< OWeakObject * >(this)); + default: + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getLongValue:" + " underlying RegistryKey::getValue() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } + return value; +} + +void Key::setLongValue(sal_Int32 value) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + RegError err = key_.setValue( + rtl::OUString(), RG_VALUETYPE_LONG, &value, sizeof (sal_Int32)); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key setLongValue:" + " underlying RegistryKey::setValue() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } +} + +css::uno::Sequence< sal_Int32 > Key::getLongListValue() throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + RegistryValueList< sal_Int32 > list; + RegError err = key_.getLongListValue(rtl::OUString(), list); + switch (err) { + case REG_NO_ERROR: + break; + case REG_VALUE_NOT_EXISTS: + return css::uno::Sequence< sal_Int32 >(); + case REG_INVALID_VALUE: + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getLongListValue:" + " underlying RegistryKey::getLongListValue() =" + " REG_INVALID_VALUE")), + static_cast< OWeakObject * >(this)); + default: + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getLongListValue:" + " underlying RegistryKey::getLongListValue() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } + sal_uInt32 n = list.getLength(); + if (n > SAL_MAX_INT32) { + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getLongListValue:" + " underlying RegistryKey::getLongListValue() too large")), + static_cast< OWeakObject * >(this)); + } + css::uno::Sequence< sal_Int32 > value(static_cast< sal_Int32 >(n)); + for (sal_uInt32 i = 0; i < n; ++i) { + value[static_cast< sal_Int32 >(i)] = list.getElement(i); + } + return value; +} + +void Key::setLongListValue(css::uno::Sequence< sal_Int32 > const & seqValue) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + std::vector< sal_Int32 > list; + for (sal_Int32 i = 0; i < seqValue.getLength(); ++i) { + list.push_back(seqValue[i]); + } + RegError err = key_.setLongListValue( + rtl::OUString(), list.empty() ? 0 : &list[0], + static_cast< sal_uInt32 >(list.size())); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key setLongListValue:" + " underlying RegistryKey::setLongListValue() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } +} + +rtl::OUString Key::getAsciiValue() throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + RegValueType type; + sal_uInt32 size; + RegError err = key_.getValueInfo(rtl::OUString(), &type, &size); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getAsciiValue:" + " underlying RegistryKey::getValueInfo() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } + if (type != RG_VALUETYPE_STRING) { + throw css::registry::InvalidValueException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getAsciiValue:" + " underlying RegistryKey type = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(type))), + static_cast< OWeakObject * >(this)); + } + // size contains terminating null (error in underlying registry.cxx): + if (size == 0) { + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getAsciiValue:" + " underlying RegistryKey size 0 cannot happen due to" + " design error")), + static_cast< OWeakObject * >(this)); + } + if (size > SAL_MAX_INT32) { + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getAsciiValue:" + " underlying RegistryKey size too large")), + static_cast< OWeakObject * >(this)); + } + std::vector< char > list(size); + err = key_.getValue(rtl::OUString(), &list[0]); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getAsciiValue:" + " underlying RegistryKey::getValue() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } + if (list[size - 1] != '\0') { + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getAsciiValue:" + " underlying RegistryKey value must be null-terminated due" + " to design error")), + static_cast< OWeakObject * >(this)); + } + rtl::OUString value; + if (!rtl_convertStringToUString( + &value.pData, &list[0], + static_cast< sal_Int32 >(size - 1), RTL_TEXTENCODING_UTF8, + (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR | + RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR | + RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR))) + { + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getAsciiValue:" + " underlying RegistryKey not UTF-8")), + static_cast< OWeakObject * >(this)); + } + return value; +} + +void Key::setAsciiValue(rtl::OUString const & value) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + rtl::OString utf8; + if (!value.convertToString( + &utf8, RTL_TEXTENCODING_UTF8, + (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR | + RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))) + { + throw css::uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key setAsciiValue:" + " value not UTF-16")), + static_cast< OWeakObject * >(this)); + } + RegError err = key_.setValue( + rtl::OUString(), RG_VALUETYPE_STRING, + const_cast< char * >(utf8.getStr()), utf8.getLength() + 1); + // +1 for terminating null (error in underlying registry.cxx) + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key setAsciiValue:" + " underlying RegistryKey::setValue() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } +} + +css::uno::Sequence< rtl::OUString > Key::getAsciiListValue() throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + RegistryValueList< char * > list; + RegError err = key_.getStringListValue(rtl::OUString(), list); + switch (err) { + case REG_NO_ERROR: + break; + case REG_VALUE_NOT_EXISTS: + return css::uno::Sequence< rtl::OUString >(); + case REG_INVALID_VALUE: + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key" + " getAsciiListValue: underlying" + " RegistryKey::getStringListValue() = REG_INVALID_VALUE")), + static_cast< OWeakObject * >(this)); + default: + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key" + " getAsciiListValue: underlying" + " RegistryKey::getStringListValue() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } + sal_uInt32 n = list.getLength(); + if (n > SAL_MAX_INT32) { + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key" + " getAsciiListValue: underlying" + " RegistryKey::getStringListValue() too large")), + static_cast< OWeakObject * >(this)); + } + css::uno::Sequence< rtl::OUString > value(static_cast< sal_Int32 >(n)); + for (sal_uInt32 i = 0; i < n; ++i) { + char * el = list.getElement(i); + sal_Int32 size = rtl_str_getLength(el); + if (!rtl_convertStringToUString( + &value[static_cast< sal_Int32 >(i)].pData, el, size, + RTL_TEXTENCODING_UTF8, + (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR | + RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR | + RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR))) + { + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key" + " getAsciiListValue: underlying RegistryKey not" + " UTF-8")), + static_cast< OWeakObject * >(this)); + } + } + return value; +} + +void Key::setAsciiListValue( + css::uno::Sequence< rtl::OUString > const & seqValue) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + std::vector< rtl::OString > list; + for (sal_Int32 i = 0; i < seqValue.getLength(); ++i) { + rtl::OString utf8; + if (!seqValue[i].convertToString( + &utf8, RTL_TEXTENCODING_UTF8, + (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR | + RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))) + { + throw css::uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key" + " setAsciiListValue: value not UTF-16")), + static_cast< OWeakObject * >(this)); + } + list.push_back(utf8); + } + std::vector< char * > list2; + for (std::vector< rtl::OString >::iterator i(list.begin()); i != list.end(); + ++i) + { + list2.push_back(const_cast< char * >(i->getStr())); + } + RegError err = key_.setStringListValue( + rtl::OUString(), list2.empty() ? 0 : &list2[0], + static_cast< sal_uInt32 >(list2.size())); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key" + " setAsciiListValue: underlying" + " RegistryKey::setStringListValue() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } +} + +rtl::OUString Key::getStringValue() throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + RegValueType type; + sal_uInt32 size; + RegError err = key_.getValueInfo(rtl::OUString(), &type, &size); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getStringValue:" + " underlying RegistryKey::getValueInfo() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } + if (type != RG_VALUETYPE_UNICODE) { + throw css::registry::InvalidValueException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getStringValue:" + " underlying RegistryKey type = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(type))), + static_cast< OWeakObject * >(this)); + } + // size contains terminating null and is *2 (error in underlying + // registry.cxx): + if (size == 0 || (size & 1) == 1) { + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getStringValue:" + " underlying RegistryKey size 0 or odd cannot happen due to" + " design error")), + static_cast< OWeakObject * >(this)); + } + if (size > SAL_MAX_INT32) { + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getStringValue:" + " underlying RegistryKey size too large")), + static_cast< OWeakObject * >(this)); + } + std::vector< sal_Unicode > list(size); + err = key_.getValue(rtl::OUString(), &list[0]); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getStringValue:" + " underlying RegistryKey::getValue() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } + if (list[size/2 - 1] != 0) { + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getStringValue:" + " underlying RegistryKey value must be null-terminated due" + " to design error")), + static_cast< OWeakObject * >(this)); + } + return rtl::OUString(&list[0], static_cast< sal_Int32 >(size/2 - 1)); +} + +void Key::setStringValue(rtl::OUString const & value) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + RegError err = key_.setValue( + rtl::OUString(), RG_VALUETYPE_UNICODE, + const_cast< sal_Unicode * >(value.getStr()), + (value.getLength() + 1) * sizeof (sal_Unicode)); + // +1 for terminating null (error in underlying registry.cxx) + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key setStringValue:" + " underlying RegistryKey::setValue() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } +} + +css::uno::Sequence< rtl::OUString > Key::getStringListValue() throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + RegistryValueList< sal_Unicode * > list; + RegError err = key_.getUnicodeListValue(rtl::OUString(), list); + switch (err) { + case REG_NO_ERROR: + break; + case REG_VALUE_NOT_EXISTS: + return css::uno::Sequence< rtl::OUString >(); + case REG_INVALID_VALUE: + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key" + " getStringListValue: underlying" + " RegistryKey::getUnicodeListValue() = REG_INVALID_VALUE")), + static_cast< OWeakObject * >(this)); + default: + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key" + " getStringListValue: underlying" + " RegistryKey::getUnicodeListValue() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } + sal_uInt32 n = list.getLength(); + if (n > SAL_MAX_INT32) { + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key" + " getStringListValue: underlying" + " RegistryKey::getUnicodeListValue() too large")), + static_cast< OWeakObject * >(this)); + } + css::uno::Sequence< rtl::OUString > value(static_cast< sal_Int32 >(n)); + for (sal_uInt32 i = 0; i < n; ++i) { + value[static_cast< sal_Int32 >(i)] = list.getElement(i); + } + return value; +} + +void Key::setStringListValue( + css::uno::Sequence< rtl::OUString > const & seqValue) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + std::vector< sal_Unicode * > list; + for (sal_Int32 i = 0; i < seqValue.getLength(); ++i) { + list.push_back(const_cast< sal_Unicode * >(seqValue[i].getStr())); + } + RegError err = key_.setUnicodeListValue( + rtl::OUString(), list.empty() ? 0 : &list[0], + static_cast< sal_uInt32 >(list.size())); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key" + " setStringListValue: underlying" + " RegistryKey::setUnicodeListValue() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } +} + +css::uno::Sequence< sal_Int8 > Key::getBinaryValue() + throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + RegValueType type; + sal_uInt32 size; + RegError err = key_.getValueInfo(rtl::OUString(), &type, &size); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getBinaryValue:" + " underlying RegistryKey::getValueInfo() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } + if (type != RG_VALUETYPE_BINARY) { + throw css::registry::InvalidValueException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getBinaryValue:" + " underlying RegistryKey type = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(type))), + static_cast< OWeakObject * >(this)); + } + if (size > SAL_MAX_INT32) { + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getBinaryValue:" + " underlying RegistryKey size too large")), + static_cast< OWeakObject * >(this)); + } + css::uno::Sequence< sal_Int8 > value(static_cast< sal_Int32 >(size)); + err = key_.getValue(rtl::OUString(), value.getArray()); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getBinaryValue:" + " underlying RegistryKey::getValue() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } + return value; +} + +void Key::setBinaryValue(css::uno::Sequence< sal_Int8 > const & value) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + RegError err = key_.setValue( + rtl::OUString(), RG_VALUETYPE_BINARY, + const_cast< sal_Int8 * >(value.getConstArray()), + static_cast< sal_uInt32 >(value.getLength())); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key setBinaryValue:" + " underlying RegistryKey::setValue() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } +} + +css::uno::Reference< css::registry::XRegistryKey > Key::openKey( + rtl::OUString const & aKeyName) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + RegistryKey key; + RegError err = key_.openKey(aKeyName, key); + switch (err) { + case REG_NO_ERROR: + return new Key(registry_, key); + case REG_KEY_NOT_EXISTS: + return css::uno::Reference< css::registry::XRegistryKey >(); + default: + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key openKey:" + " underlying RegistryKey::openKey() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } +} + +css::uno::Reference< css::registry::XRegistryKey > Key::createKey( + rtl::OUString const & aKeyName) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + RegistryKey key; + RegError err = key_.createKey(aKeyName, key); + switch (err) { + case REG_NO_ERROR: + return new Key(registry_, key); + case REG_INVALID_KEYNAME: + return css::uno::Reference< css::registry::XRegistryKey >(); + default: + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key createKey:" + " underlying RegistryKey::createKey() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } +} + +void Key::closeKey() + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + RegError err = key_.closeKey(); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key closeKey:" + " underlying RegistryKey::closeKey() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } +} + +void Key::deleteKey(rtl::OUString const & rKeyName) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + RegError err = key_.deleteKey(rKeyName); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key deleteKey:" + " underlying RegistryKey::deleteKey() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } +} + +css::uno::Sequence< css::uno::Reference< css::registry::XRegistryKey > > +Key::openKeys() + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + RegistryKeyArray list; + RegError err = key_.openSubKeys(rtl::OUString(), list); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key openKeys:" + " underlying RegistryKey::openSubKeys() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } + sal_uInt32 n = list.getLength(); + if (n > SAL_MAX_INT32) { + throw css::registry::InvalidRegistryException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getKeyNames:" + " underlying RegistryKey::getKeyNames() too large")), + static_cast< OWeakObject * >(this)); + } + css::uno::Sequence< css::uno::Reference< css::registry::XRegistryKey > > + keys(static_cast< sal_Int32 >(n)); + for (sal_uInt32 i = 0; i < n; ++i) { + keys[static_cast< sal_Int32 >(i)] = new Key( + registry_, list.getElement(i)); + } + return keys; +} + +css::uno::Sequence< rtl::OUString > Key::getKeyNames() + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + RegistryKeyNames list; + RegError err = key_.getKeyNames(rtl::OUString(), list); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getKeyNames:" + " underlying RegistryKey::getKeyNames() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } + sal_uInt32 n = list.getLength(); + if (n > SAL_MAX_INT32) { + throw css::registry::InvalidRegistryException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getKeyNames:" + " underlying RegistryKey::getKeyNames() too large")), + static_cast< OWeakObject * >(this)); + } + css::uno::Sequence< rtl::OUString > names(static_cast< sal_Int32 >(n)); + for (sal_uInt32 i = 0; i < n; ++i) { + names[static_cast< sal_Int32 >(i)] = list.getElement(i); + } + return names; +} + +sal_Bool Key::createLink( + rtl::OUString const & aLinkName, rtl::OUString const & aLinkTarget) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + RegError err = key_.createLink(aLinkName, aLinkTarget); + switch (err) { + case REG_NO_ERROR: + return true; + case REG_INVALID_KEY: + case REG_DETECT_RECURSION: + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key createLink:" + " underlying RegistryKey::createLink() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + default: + return false; + } +} + +void Key::deleteLink(rtl::OUString const & rLinkName) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + RegError err = key_.deleteLink(rLinkName); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key deleteLink:" + " underlying RegistryKey::deleteLink() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } +} + +rtl::OUString Key::getLinkTarget(rtl::OUString const & rLinkName) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + rtl::OUString target; + RegError err = key_.getLinkTarget(rLinkName, target); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getLinkTarget:" + " underlying RegistryKey::getLinkTarget() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } + return target; +} + +rtl::OUString Key::getResolvedName(rtl::OUString const & aKeyName) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(registry_->mutex_); + rtl::OUString resolved; + RegError err = key_.getResolvedKeyName(aKeyName, true, resolved); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry key getResolvedName:" + " underlying RegistryKey::getResolvedName() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } + return resolved; +} + +rtl::OUString SimpleRegistry::getURL() throw (css::uno::RuntimeException) { + osl::MutexGuard guard(mutex_); + return textual_.get() == 0 ? registry_.getName() : textual_->getUri(); +} + +void SimpleRegistry::open( + rtl::OUString const & rURL, sal_Bool bReadOnly, sal_Bool bCreate) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(mutex_); + if (textual_.get() != 0) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry.open(")) + + rURL + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "): instance already open"))), + static_cast< OWeakObject * >(this)); + } + RegError err = (rURL.getLength() == 0 && bCreate) + ? REG_REGISTRY_NOT_EXISTS + : registry_.open(rURL, bReadOnly ? REG_READONLY : REG_READWRITE); + if (err == REG_REGISTRY_NOT_EXISTS && bCreate) { + err = registry_.create(rURL); + } + switch (err) { + case REG_NO_ERROR: + break; + case REG_INVALID_REGISTRY: + if (bReadOnly && !bCreate) { + textual_.reset(new stoc::simpleregistry::TextualServices(rURL)); + break; + } + // fall through + default: + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry.open(")) + + rURL + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "): underlying Registry::open/create() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } +} + +sal_Bool SimpleRegistry::isValid() throw (css::uno::RuntimeException) { + osl::MutexGuard guard(mutex_); + return textual_.get() != 0 || registry_.isValid(); +} + +void SimpleRegistry::close() + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(mutex_); + if (textual_.get() != 0) { + textual_.reset(); + return; + } + RegError err = registry_.close(); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry.close:" + " underlying Registry::close() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } +} + +void SimpleRegistry::destroy() + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(mutex_); + if (textual_.get() != 0) { + textual_.reset(); + return; + } + RegError err = registry_.destroy(rtl::OUString()); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry.destroy:" + " underlying Registry::destroy() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } +} + +css::uno::Reference< css::registry::XRegistryKey > SimpleRegistry::getRootKey() + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(mutex_); + if (textual_.get() != 0) { + return textual_->getRootKey(); + } + RegistryKey root; + RegError err = registry_.openRootKey(root); + if (err != REG_NO_ERROR) { + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry.getRootKey:" + " underlying Registry::getRootKey() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } + return new Key(this, root); +} + +sal_Bool SimpleRegistry::isReadOnly() + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(mutex_); + return textual_.get() != 0 || registry_.isReadOnly(); +} + +void SimpleRegistry::mergeKey( + rtl::OUString const & aKeyName, rtl::OUString const & aUrl) + throw ( + css::registry::InvalidRegistryException, + css::registry::MergeConflictException, css::uno::RuntimeException) +{ + osl::MutexGuard guard(mutex_); + if (textual_.get() != 0) { + throw css::uno::RuntimeException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry.mergeKey: not" + " supported for textual representation")), + static_cast< cppu::OWeakObject * >(this)); + } + RegistryKey root; + RegError err = registry_.openRootKey(root); + if (err == REG_NO_ERROR) { + err = registry_.mergeKey(root, aKeyName, aUrl, false, false); + } + switch (err) { + case REG_NO_ERROR: + case REG_MERGE_CONFLICT: + break; + case REG_MERGE_ERROR: + throw css::registry::MergeConflictException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry.mergeKey:" + " underlying Registry::mergeKey() = REG_MERGE_ERROR")), + static_cast< cppu::OWeakObject * >(this)); + default: + throw css::registry::InvalidRegistryException( + (rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry.mergeKey:" + " underlying Registry::getRootKey/mergeKey() = ")) + + rtl::OUString::valueOf(static_cast< sal_Int32 >(err))), + static_cast< OWeakObject * >(this)); + } +} + +} + +namespace stoc_bootstrap { + +css::uno::Reference< css::uno::XInterface > SimpleRegistry_CreateInstance( + css::uno::Reference< css::uno::XComponentContext > const &) +{ + return static_cast< cppu::OWeakObject * >(new SimpleRegistry); +} + +css::uno::Sequence< rtl::OUString > simreg_getSupportedServiceNames() { + css::uno::Sequence< rtl::OUString > names(1); + names[0] = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.registry.SimpleRegistry")); + return names; +} + +rtl::OUString simreg_getImplementationName() { + return rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.stoc.SimpleRegistry")); +} + +} diff --git a/stoc/source/simpleregistry/textualservices.cxx b/stoc/source/simpleregistry/textualservices.cxx new file mode 100644 index 000000000000..5a50a5aa62c6 --- /dev/null +++ b/stoc/source/simpleregistry/textualservices.cxx @@ -0,0 +1,1228 @@ +/************************************************************************* +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +* +************************************************************************/ + +#include "precompiled_stoc.hxx" +#include "sal/config.h" + +#include <cstddef> +#include <cstdlib> +#include <map> +#include <vector> + +#include "boost/noncopyable.hpp" +#include "com/sun/star/container/NoSuchElementException.hpp" +#include "com/sun/star/registry/InvalidRegistryException.hpp" +#include "com/sun/star/registry/XRegistryKey.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/XInterface.hpp" +#include "cppuhelper/implbase1.hxx" +#include "osl/diagnose.h" +#include "rtl/malformeduriexception.hxx" +#include "rtl/ref.hxx" +#include "rtl/string.h" +#include "rtl/uri.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "salhelper/simplereferenceobject.hxx" +#include "xmlreader/span.hxx" +#include "xmlreader/xmlreader.hxx" + +#include "textualservices.hxx" + +namespace stoc { namespace simpleregistry { + +namespace { + +namespace css = com::sun::star; + +struct Implementation { + rtl::OUString uri; + rtl::OUString loader; + std::vector< rtl::OUString > services; + std::vector< rtl::OUString > singletons; +}; + +typedef std::map< rtl::OUString, Implementation > Implementations; + +typedef std::map< rtl::OUString, std::vector< rtl::OUString > > + ImplementationMap; + +} + +class Data: public salhelper::SimpleReferenceObject, private boost::noncopyable +{ +public: + Implementations implementations; + ImplementationMap services; + ImplementationMap singletons; +}; + +namespace { + +class Parser: private boost::noncopyable { +public: + Parser(rtl::OUString const & uri, rtl::Reference< Data > const & data); + +private: + void handleComponent(); + + void handleImplementation(); + + void handleService(); + + void handleSingleton(); + + rtl::OUString getNameAttribute(); + + xmlreader::XmlReader reader_; + rtl::Reference< Data > data_; + rtl::OUString attrUri_; + rtl::OUString attrLoader_; + rtl::OUString attrImplementation_; +}; + +Parser::Parser(rtl::OUString const & uri, rtl::Reference< Data > const & data): + reader_(uri), data_(data) +{ + OSL_ASSERT(data.is()); + int ucNsId = reader_.registerNamespaceIri( + xmlreader::Span( + RTL_CONSTASCII_STRINGPARAM( + "http://openoffice.org/2010/uno-components"))); + enum State { + STATE_BEGIN, STATE_END, STATE_COMPONENTS, STATE_COMPONENT_INITIAL, + STATE_COMPONENT, STATE_IMPLEMENTATION, STATE_SERVICE, STATE_SINGLETON }; + for (State state = STATE_BEGIN;;) { + xmlreader::Span name; + int nsId; + xmlreader::XmlReader::Result res = reader_.nextItem( + xmlreader::XmlReader::TEXT_NONE, &name, &nsId); + switch (state) { + case STATE_BEGIN: + if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId && + name.equals(RTL_CONSTASCII_STRINGPARAM("components"))) + { + state = STATE_COMPONENTS; + break; + } + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + ": unexpected item in outer level"))), + css::uno::Reference< css::uno::XInterface >()); + case STATE_END: + if (res == xmlreader::XmlReader::RESULT_DONE) { + return; + } + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + ": unexpected item in outer level"))), + css::uno::Reference< css::uno::XInterface >()); + case STATE_COMPONENTS: + if (res == xmlreader::XmlReader::RESULT_END) { + state = STATE_END; + break; + } + if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId && + name.equals(RTL_CONSTASCII_STRINGPARAM("component"))) + { + handleComponent(); + state = STATE_COMPONENT_INITIAL; + break; + } + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + ": unexpected item in <components>"))), + css::uno::Reference< css::uno::XInterface >()); + case STATE_COMPONENT: + if (res == xmlreader::XmlReader::RESULT_END) { + state = STATE_COMPONENTS; + break; + } + // fall through + case STATE_COMPONENT_INITIAL: + if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId && + name.equals(RTL_CONSTASCII_STRINGPARAM("implementation"))) + { + handleImplementation(); + state = STATE_IMPLEMENTATION; + break; + } + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + ": unexpected item in <component>"))), + css::uno::Reference< css::uno::XInterface >()); + case STATE_IMPLEMENTATION: + if (res == xmlreader::XmlReader::RESULT_END) { + state = STATE_COMPONENT; + break; + } + if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId && + name.equals(RTL_CONSTASCII_STRINGPARAM("service"))) + { + handleService(); + state = STATE_SERVICE; + break; + } + if (res == xmlreader::XmlReader::RESULT_BEGIN && nsId == ucNsId && + name.equals(RTL_CONSTASCII_STRINGPARAM("singleton"))) + { + handleSingleton(); + state = STATE_SINGLETON; + break; + } + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + ": unexpected item in <implementation>"))), + css::uno::Reference< css::uno::XInterface >()); + case STATE_SERVICE: + if (res == xmlreader::XmlReader::RESULT_END) { + state = STATE_IMPLEMENTATION; + break; + } + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + ": unexpected item in <service>"))), + css::uno::Reference< css::uno::XInterface >()); + case STATE_SINGLETON: + if (res == xmlreader::XmlReader::RESULT_END) { + state = STATE_IMPLEMENTATION; + break; + } + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + ": unexpected item in <service>"))), + css::uno::Reference< css::uno::XInterface >()); + } + } +} + +void Parser::handleComponent() { + attrUri_ = rtl::OUString(); + attrLoader_ = rtl::OUString(); + xmlreader::Span name; + int nsId; + while (reader_.nextAttribute(&nsId, &name)) { + if (nsId == xmlreader::XmlReader::NAMESPACE_NONE && + name.equals(RTL_CONSTASCII_STRINGPARAM("uri"))) + { + if (attrUri_.getLength() != 0) { + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + ": <component> has multiple \"uri\" attributes"))), + css::uno::Reference< css::uno::XInterface >()); + } + attrUri_ = reader_.getAttributeValue(false).convertFromUtf8(); + if (attrUri_.getLength() == 0) { + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + ": <component> has empty \"uri\" attribute"))), + css::uno::Reference< css::uno::XInterface >()); + } + } else if (nsId == xmlreader::XmlReader::NAMESPACE_NONE && + name.equals(RTL_CONSTASCII_STRINGPARAM("loader"))) + { + if (attrLoader_.getLength() != 0) { + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + ": <component> has multiple \"loader\"" + " attributes"))), + css::uno::Reference< css::uno::XInterface >()); + } + attrLoader_ = reader_.getAttributeValue(false).convertFromUtf8(); + if (attrLoader_.getLength() == 0) { + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + ": <component> has empty \"loader\" attribute"))), + css::uno::Reference< css::uno::XInterface >()); + } + } else { + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + ": expected <component> attribute \"uri\" or" + " \"loader\""))), + css::uno::Reference< css::uno::XInterface >()); + } + } + if (attrUri_.getLength() == 0) { + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + ": <component> is missing \"uri\" attribute"))), + css::uno::Reference< css::uno::XInterface >()); + } + if (attrLoader_.getLength() == 0) { + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + ": <component> is missing \"loader\" attribute"))), + css::uno::Reference< css::uno::XInterface >()); + } + try { + attrUri_ = rtl::Uri::convertRelToAbs(reader_.getUrl(), attrUri_); + } catch (rtl::MalformedUriException & e) { + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM(": bad \"uri\" attribute: ")) + + e.getMessage()), + css::uno::Reference< css::uno::XInterface >()); + } +} + +void Parser::handleImplementation() { + attrImplementation_ = getNameAttribute(); + if (data_->implementations.find(attrImplementation_) != + data_->implementations.end()) + { + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + ": duplicate <implementation name=\"")) + + attrImplementation_ + + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("\">"))), + css::uno::Reference< css::uno::XInterface >()); + } + data_->implementations[attrImplementation_].uri = attrUri_; + data_->implementations[attrImplementation_].loader = attrLoader_; +} + +void Parser::handleService() { + rtl::OUString name = getNameAttribute(); + data_->implementations[attrImplementation_].services.push_back(name); + data_->services[name].push_back(attrImplementation_); +} + +void Parser::handleSingleton() { + rtl::OUString name = getNameAttribute(); + data_->implementations[attrImplementation_].singletons.push_back(name); + data_->singletons[name].push_back(attrImplementation_); +} + +rtl::OUString Parser::getNameAttribute() { + rtl::OUString attrName; + xmlreader::Span name; + int nsId; + while (reader_.nextAttribute(&nsId, &name)) { + if (nsId == xmlreader::XmlReader::NAMESPACE_NONE && + name.equals(RTL_CONSTASCII_STRINGPARAM("name"))) + { + if (attrName.getLength() != 0) { + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + ": element has multiple \"name\" attributes"))), + css::uno::Reference< css::uno::XInterface >()); + } + attrName = reader_.getAttributeValue(false).convertFromUtf8(); + if (attrName.getLength() == 0) { + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + ": element has empty \"name\" attribute"))), + css::uno::Reference< css::uno::XInterface >()); + } + } else { + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + ": expected element attribute \"name\""))), + css::uno::Reference< css::uno::XInterface >()); + } + } + if (attrName.getLength() == 0) { + throw css::registry::InvalidRegistryException( + (reader_.getUrl() + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + ": element is missing \"name\" attribute"))), + css::uno::Reference< css::uno::XInterface >()); + } + return attrName; +} + +rtl::OUString pathToString(std::vector< rtl::OUString > const & path) { + rtl::OUStringBuffer buf; + for (std::vector< rtl::OUString >::const_iterator i(path.begin()); + i != path.end(); ++i) + { + buf.append(sal_Unicode('/')); + buf.append(*i); + } + if (buf.getLength() == 0) { + buf.append(sal_Unicode('/')); + } + return buf.makeStringAndClear(); +} + +class Key: public cppu::WeakImplHelper1< css::registry::XRegistryKey > { +public: + Key( + rtl::Reference< Data > const & data, + std::vector< rtl::OUString > const & path): + data_(data), path_(path) { OSL_ASSERT(data.is()); + } + +private: + /* + / + IMPLEMENTATIONS + <implementation> + UNO + LOCATION utf-8 + ACTIVATOR utf-8 + SERVICES + <service> + ... + SINGLETONS + <singleton> utf-16 + ... + ... + SERVICES + <service> utf-8-list + ... + SINGLETONS + <singleton> utf-16 + REGISTERED_BY utf-8-list + ... + */ + enum State { + STATE_ROOT, STATE_IMPLEMENTATIONS, STATE_IMPLEMENTATION, STATE_UNO, + STATE_LOCATION, STATE_ACTIVATOR, STATE_IMPLEMENTATION_SERVICES, + STATE_IMPLEMENTATION_SERVICE, STATE_IMPLEMENTATION_SINGLETONS, + STATE_IMPLEMENTATION_SINGLETON, STATE_SERVICES, STATE_SERVICE, + STATE_SINGLETONS, STATE_SINGLETON, STATE_REGISTEREDBY }; + + virtual rtl::OUString SAL_CALL getKeyName() + throw (css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isReadOnly() throw ( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL isValid() throw(css::uno::RuntimeException); + + virtual css::registry::RegistryKeyType SAL_CALL getKeyType( + rtl::OUString const & rKeyName) + throw ( + css::registry::InvalidRegistryException, + css::uno::RuntimeException); + + virtual css::registry::RegistryValueType SAL_CALL getValueType() throw( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getLongValue() throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException); + + virtual void SAL_CALL setLongValue(sal_Int32 value) throw ( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual css::uno::Sequence< sal_Int32 > SAL_CALL getLongListValue() throw( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException); + + virtual void SAL_CALL setLongListValue( + com::sun::star::uno::Sequence< sal_Int32 > const & seqValue) + throw ( + css::registry::InvalidRegistryException, + css::uno::RuntimeException); + + virtual rtl::OUString SAL_CALL getAsciiValue() throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException); + + virtual void SAL_CALL setAsciiValue(rtl::OUString const & value) throw ( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL getAsciiListValue() + throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException); + + virtual void SAL_CALL setAsciiListValue( + css::uno::Sequence< rtl::OUString > const & seqValue) + throw ( + css::registry::InvalidRegistryException, + css::uno::RuntimeException); + + virtual rtl::OUString SAL_CALL getStringValue() throw( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException); + + virtual void SAL_CALL setStringValue(rtl::OUString const & value) throw ( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL getStringListValue() + throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException); + + virtual void SAL_CALL setStringListValue( + css::uno::Sequence< rtl::OUString > const & seqValue) + throw ( + css::registry::InvalidRegistryException, + css::uno::RuntimeException); + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getBinaryValue() throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException); + + virtual void SAL_CALL setBinaryValue( + css::uno::Sequence< sal_Int8 > const & value) + throw ( + css::registry::InvalidRegistryException, + css::uno::RuntimeException); + + virtual css::uno::Reference< css::registry::XRegistryKey > SAL_CALL openKey( + rtl::OUString const & aKeyName) + throw ( + css::registry::InvalidRegistryException, + css::uno::RuntimeException); + + virtual css::uno::Reference< css::registry::XRegistryKey > SAL_CALL + createKey(rtl::OUString const & aKeyName) throw ( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual void SAL_CALL closeKey() throw ( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual void SAL_CALL deleteKey(rtl::OUString const & rKeyName) throw ( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual + css::uno::Sequence< css::uno::Reference< css::registry::XRegistryKey > > + SAL_CALL openKeys() throw ( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL getKeyNames() throw ( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL createLink( + rtl::OUString const & aLinkName, rtl::OUString const & aLinkTarget) + throw ( + css::registry::InvalidRegistryException, + css::uno::RuntimeException); + + virtual void SAL_CALL deleteLink(rtl::OUString const & rLinkName) throw ( + css::registry::InvalidRegistryException, css::uno::RuntimeException); + + virtual rtl::OUString SAL_CALL getLinkTarget( + rtl::OUString const & rLinkName) + throw ( + css::registry::InvalidRegistryException, + css::uno::RuntimeException); + + virtual rtl::OUString SAL_CALL getResolvedName( + rtl::OUString const & aKeyName) + throw ( + css::registry::InvalidRegistryException, + css::uno::RuntimeException); + + bool find( + rtl::OUString const & relative, std::vector< rtl::OUString > * path, + State * state, css::registry::RegistryValueType * type) const; + + css::uno::Sequence< rtl::OUString > getChildren(); + + rtl::Reference< Data > data_; + std::vector< rtl::OUString > path_; +}; + +rtl::OUString Key::getKeyName() throw (css::uno::RuntimeException) { + return pathToString(path_); +} + +sal_Bool Key::isReadOnly() + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + return true; +} + +sal_Bool Key::isValid() throw(css::uno::RuntimeException) { + return true; +} + +css::registry::RegistryKeyType Key::getKeyType(rtl::OUString const & rKeyName) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + if (!find(rtl::OUString(), 0, 0, 0)) { + throw css::registry::InvalidRegistryException( + (rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("unknown key ")) + + rKeyName), + static_cast< cppu::OWeakObject * >(this)); + } + return css::registry::RegistryKeyType_KEY; +} + +css::registry::RegistryValueType Key::getValueType() + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + css::registry::RegistryValueType type = + css::registry::RegistryValueType_NOT_DEFINED; + OSL_VERIFY(find(rtl::OUString(), 0, 0, &type)); + return type; +} + +sal_Int32 Key::getLongValue() throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException) +{ + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual services key" + " getLongValue not supported")), + static_cast< OWeakObject * >(this)); +} + +void Key::setLongValue(sal_Int32) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + throw css::registry::InvalidRegistryException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual services key" + " setLongValue not supported")), + static_cast< OWeakObject * >(this)); +} + +css::uno::Sequence< sal_Int32 > Key::getLongListValue() throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException) +{ + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual services key" + " getLongListValue not supported")), + static_cast< OWeakObject * >(this)); +} + +void Key::setLongListValue(css::uno::Sequence< sal_Int32 > const &) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + throw css::registry::InvalidRegistryException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual services key" + " setLongListValue not supported")), + static_cast< OWeakObject * >(this)); +} + +rtl::OUString Key::getAsciiValue() throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException) +{ + State state = STATE_ROOT; + OSL_VERIFY(find(rtl::OUString(), 0, &state, 0)); + switch (state) { + case STATE_LOCATION: + return data_->implementations[path_[1]].uri; + case STATE_ACTIVATOR: + return data_->implementations[path_[1]].loader; + default: + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual services key" + " getAsciiValue: wrong type")), + static_cast< OWeakObject * >(this)); + } +} + +void Key::setAsciiValue(rtl::OUString const &) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + throw css::registry::InvalidRegistryException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual services key" + " setAsciiValue not supported")), + static_cast< OWeakObject * >(this)); +} + +css::uno::Sequence< rtl::OUString > Key::getAsciiListValue() throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException) +{ + State state = STATE_ROOT; + OSL_VERIFY(find(rtl::OUString(), 0, &state, 0)); + std::vector< rtl::OUString > const * list; + switch (state) { + case STATE_SERVICE: + list = &data_->services[path_[1]]; + break; + case STATE_REGISTEREDBY: + list = &data_->singletons[path_[1]]; + break; + default: + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual services key" + " getAsciiListValue: wrong type")), + static_cast< OWeakObject * >(this)); + } + if (list->size() > SAL_MAX_INT32) { + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual services key" + " getAsciiListValue: too large")), + static_cast< OWeakObject * >(this)); + } + css::uno::Sequence< rtl::OUString > seq( + static_cast< sal_Int32 >(list->size())); + sal_Int32 i = 0; + for (std::vector< rtl::OUString >::const_iterator j(list->begin()); + j != list->end(); ++j) + { + seq[i++] = *j; + } + return seq; +} + +void Key::setAsciiListValue(css::uno::Sequence< rtl::OUString > const &) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + throw css::registry::InvalidRegistryException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual services key" + " setAsciiListValue not supported")), + static_cast< OWeakObject * >(this)); +} + +rtl::OUString Key::getStringValue() throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException) +{ + State state = STATE_ROOT; + OSL_VERIFY(find(rtl::OUString(), 0, &state, 0)); + switch (state) { + case STATE_IMPLEMENTATION_SINGLETON: + case STATE_SINGLETON: + throw css::registry::InvalidRegistryException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual services key" + " getStringValue: does not associate singletons with" + " services")), + static_cast< OWeakObject * >(this)); + default: + break; + } + // default case extracted from switch to avoid erroneous compiler warnings + // on Solaris: + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual services key" + " getStringValue: wrong type")), + static_cast< OWeakObject * >(this)); +} + +void Key::setStringValue(rtl::OUString const &) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + throw css::registry::InvalidRegistryException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual services key" + " setStringValue not supported")), + static_cast< OWeakObject * >(this)); +} + +css::uno::Sequence< rtl::OUString > Key::getStringListValue() throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException) +{ + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual services key" + " getStringListValue not supported")), + static_cast< OWeakObject * >(this)); +} + +void Key::setStringListValue(css::uno::Sequence< rtl::OUString > const &) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + throw css::registry::InvalidRegistryException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual services key" + " setStringListValue not supported")), + static_cast< OWeakObject * >(this)); +} + +css::uno::Sequence< sal_Int8 > Key::getBinaryValue() + throw ( + css::registry::InvalidRegistryException, + css::registry::InvalidValueException, css::uno::RuntimeException) +{ + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual services key" + " getBinarValue not supported")), + static_cast< OWeakObject * >(this)); +} + +void Key::setBinaryValue(css::uno::Sequence< sal_Int8 > const &) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + throw css::registry::InvalidRegistryException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual services key" + " setBinaryValue not supported")), + static_cast< OWeakObject * >(this)); +} + +css::uno::Reference< css::registry::XRegistryKey > Key::openKey( + rtl::OUString const & aKeyName) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + std::vector< rtl::OUString > path; + if (!find(aKeyName, &path, 0, 0)) { + return css::uno::Reference< css::registry::XRegistryKey >(); + } + return new Key(data_, path); +} + +css::uno::Reference< css::registry::XRegistryKey > Key::createKey( + rtl::OUString const &) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + throw css::registry::InvalidRegistryException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual services key" + " createKey not supported")), + static_cast< OWeakObject * >(this)); +} + +void Key::closeKey() + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{} + +void Key::deleteKey(rtl::OUString const &) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + throw css::registry::InvalidRegistryException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual services key" + " deleteKey not supported")), + static_cast< OWeakObject * >(this)); +} + +css::uno::Sequence< css::uno::Reference< css::registry::XRegistryKey > > +Key::openKeys() + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + css::uno::Sequence< rtl::OUString > names(getChildren()); + css::uno::Sequence< css::uno::Reference< css::registry::XRegistryKey > > + keys(names.getLength()); + for (sal_Int32 i = 0; i < keys.getLength(); ++i) { + keys[i] = openKey(names[i]); + OSL_ASSERT(keys[i].is()); + } + return keys; +} + +css::uno::Sequence< rtl::OUString > Key::getKeyNames() + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + css::uno::Sequence< rtl::OUString > names(getChildren()); + rtl::OUString prefix(pathToString(path_)); + prefix += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/")); + for (sal_Int32 i = 0; i < names.getLength(); ++i) { + names[i] = prefix + names[i]; + } + return names; +} + +sal_Bool Key::createLink(rtl::OUString const &, rtl::OUString const &) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + throw css::registry::InvalidRegistryException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual services key" + " createLink not supported")), + static_cast< OWeakObject * >(this)); +} + +void Key::deleteLink(rtl::OUString const &) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + throw css::registry::InvalidRegistryException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual services key" + " deleteLink not supported")), + static_cast< OWeakObject * >(this)); +} + +rtl::OUString Key::getLinkTarget(rtl::OUString const &) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + throw css::registry::InvalidRegistryException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual services key" + " getLinkTarget not supported")), + static_cast< OWeakObject * >(this)); +} + +rtl::OUString Key::getResolvedName(rtl::OUString const & aKeyName) + throw (css::registry::InvalidRegistryException, css::uno::RuntimeException) +{ + std::vector< rtl::OUString > path; + find(aKeyName, &path, 0, 0); + return pathToString(path); +} + +bool Key::find( + rtl::OUString const & relative, std::vector< rtl::OUString > * path, + State * state, css::registry::RegistryValueType * type) const +{ + std::vector< rtl::OUString > p(path_); + sal_Int32 i = 0; + do { + rtl::OUString seg(relative.getToken(0, '/', i)); + if (seg.getLength() != 0) { + p.push_back(seg); + } + } while (i >= 0); + if (path != 0) { + *path = p; + } + std::size_t const MAX_TRANSITIONS = 4; + struct StateInfo { + css::registry::RegistryValueType type; + std::size_t count; + struct { char const * segment; State state; } + transitions[MAX_TRANSITIONS]; + }; + static StateInfo const info[] = { + // STATE_ROOT: + { css::registry::RegistryValueType_NOT_DEFINED, 3, + { { "IMPLEMENTATIONS", STATE_IMPLEMENTATIONS }, + { "SERVICES", STATE_SERVICES }, + { "SINGLETONS", STATE_SINGLETONS } } }, + // STATE_IMPLEMENTATIONS: + { css::registry::RegistryValueType_NOT_DEFINED, 1, + { { 0, STATE_IMPLEMENTATION } } }, + // STATE_IMPLEMENTATION: + { css::registry::RegistryValueType_NOT_DEFINED, 1, + { { "UNO", STATE_UNO } } }, + // STATE_UNO: + { css::registry::RegistryValueType_NOT_DEFINED, 4, + { { "LOCATION", STATE_LOCATION }, + { "ACTIVATOR", STATE_ACTIVATOR }, + { "SERVICES", STATE_IMPLEMENTATION_SERVICES }, + { "SINGLETONS", STATE_IMPLEMENTATION_SINGLETONS } } }, + // STATE_LOCATION: + { css::registry::RegistryValueType_ASCII, 0, {} }, + // STATE_ACTIVATOR: + { css::registry::RegistryValueType_ASCII, 0, {} }, + // STATE_IMPLEMENTATION_SERVICES: + { css::registry::RegistryValueType_NOT_DEFINED, 1, + { { 0, STATE_IMPLEMENTATION_SERVICE } } }, + // STATE_IMPLEMENTATION_SERVICE: + { css::registry::RegistryValueType_NOT_DEFINED, 0, {} }, + // STATE_IMPLEMENTATION_SINGLETONS: + { css::registry::RegistryValueType_NOT_DEFINED, 1, + { { 0, STATE_IMPLEMENTATION_SINGLETON } } }, + // STATE_IMPLEMENTATION_SINGLETON: + { css::registry::RegistryValueType_STRING, 0, {} }, + // STATE_SERVICES: + { css::registry::RegistryValueType_NOT_DEFINED, 1, + { { 0, STATE_SERVICE } } }, + // STATE_SERVICE: + { css::registry::RegistryValueType_ASCIILIST, 0, {} }, + // STATE_SINGLETONS: + { css::registry::RegistryValueType_NOT_DEFINED, 1, + { { 0, STATE_SINGLETON } } }, + // STATE_SINGLETON: + { css::registry::RegistryValueType_STRING, 1, + { { "REGISTERED_BY", STATE_REGISTEREDBY } } }, + // STATE_REGISTEREDBY: + { css::registry::RegistryValueType_ASCIILIST, 0, {} } }; + State s = STATE_ROOT; + for (std::vector< rtl::OUString >::iterator j(p.begin()); j != p.end(); ++j) + { + bool found = false; + for (std::size_t k = 0; k < info[s].count; ++k) { + if (info[s].transitions[k].segment == 0) { + switch (info[s].transitions[k].state) { + case STATE_IMPLEMENTATION: + found = data_->implementations.find(*j) != + data_->implementations.end(); + break; + case STATE_IMPLEMENTATION_SERVICE: + case STATE_IMPLEMENTATION_SINGLETON: + found = true; //TODO + break; + case STATE_SERVICE: + found = data_->services.find(*j) != data_->services.end(); + break; + case STATE_SINGLETON: + found = data_->singletons.find(*j) != + data_->singletons.end(); + break; + default: + std::abort(); // this cannot happen + } + } else { + found = j->equalsAscii(info[s].transitions[k].segment); + } + if (found) { + s = info[s].transitions[k].state; + break; + } + } + if (!found) { + return false; + } + } + if (state != 0) { + *state = s; + } + if (type != 0) { + *type = info[s].type; + } + return true; +} + +css::uno::Sequence< rtl::OUString > Key::getChildren() { + State state = STATE_ROOT; + OSL_VERIFY(find(rtl::OUString(), 0, &state, 0)); + switch (state) { + default: + std::abort(); // this cannot happen + // pseudo-fall-through to avoid warnings on MSC + case STATE_ROOT: + { + css::uno::Sequence< rtl::OUString > seq(3); + seq[0] = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("IMPLEMENTATIONS")); + seq[1] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SERVICES")); + seq[2] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SINGLETONS")); + return seq; + } + case STATE_IMPLEMENTATIONS: + { + if (data_->implementations.size() > SAL_MAX_INT32) { + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual" + " services key openKeys: too large")), + static_cast< OWeakObject * >(this)); + } + css::uno::Sequence< rtl::OUString > seq( + static_cast< sal_Int32 >(data_->implementations.size())); + sal_Int32 i = 0; + for (Implementations::iterator j(data_->implementations.begin()); + j != data_->implementations.end(); ++j) + { + seq[i++] = j->first; + } + return seq; + } + case STATE_UNO: + { + css::uno::Sequence< rtl::OUString > seq(4); + seq[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("LOCATION")); + seq[1] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ACTIVATOR")); + seq[2] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SERVICES")); + seq[3] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SINGLETONS")); + return seq; + } + case STATE_LOCATION: + case STATE_ACTIVATOR: + case STATE_IMPLEMENTATION_SERVICE: + case STATE_IMPLEMENTATION_SINGLETON: + case STATE_SERVICE: + case STATE_REGISTEREDBY: + return css::uno::Sequence< rtl::OUString >(); + case STATE_IMPLEMENTATION_SERVICES: + { + if (data_->implementations[path_[1]].services.size() > + SAL_MAX_INT32) + { + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual" + " services key openKeys: too large")), + static_cast< OWeakObject * >(this)); + } + css::uno::Sequence< rtl::OUString > seq( + static_cast< sal_Int32 >( + data_->implementations[path_[1]].services.size())); + sal_Int32 i = 0; + for (std::vector< rtl::OUString >::iterator j( + data_->implementations[path_[1]].services.begin()); + j != data_->implementations[path_[1]].services.end(); ++j) + { + seq[i++] = *j; + } + return seq; + } + case STATE_IMPLEMENTATION_SINGLETONS: + { + if (data_->implementations[path_[1]].singletons.size() > + SAL_MAX_INT32) + { + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual" + " services key openKeys: too large")), + static_cast< OWeakObject * >(this)); + } + css::uno::Sequence< rtl::OUString > seq( + static_cast< sal_Int32 >( + data_->implementations[path_[1]].singletons.size())); + sal_Int32 i = 0; + for (std::vector< rtl::OUString >::iterator j( + data_->implementations[path_[1]].singletons.begin()); + j != data_->implementations[path_[1]].singletons.end(); ++j) + { + seq[i++] = *j; + } + return seq; + } + case STATE_SERVICES: + { + if (data_->services.size() > SAL_MAX_INT32) { + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual" + " services key openKeys: too large")), + static_cast< OWeakObject * >(this)); + } + css::uno::Sequence< rtl::OUString > seq( + static_cast< sal_Int32 >(data_->services.size())); + sal_Int32 i = 0; + for (ImplementationMap::iterator j(data_->services.begin()); + j != data_->services.end(); ++j) + { + seq[i++] = j->first; + } + return seq; + } + case STATE_SINGLETONS: + { + if (data_->singletons.size() > SAL_MAX_INT32) { + throw css::registry::InvalidValueException( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry textual" + " services key openKeys: too large")), + static_cast< OWeakObject * >(this)); + } + css::uno::Sequence< rtl::OUString > seq( + static_cast< sal_Int32 >(data_->singletons.size())); + sal_Int32 i = 0; + for (ImplementationMap::iterator j(data_->singletons.begin()); + j != data_->singletons.end(); ++j) + { + seq[i++] = j->first; + } + return seq; + } + case STATE_SINGLETON: + { + css::uno::Sequence< rtl::OUString > seq(1); + seq[0] = rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("REGISTERED_BY")); + return seq; + } + } +} + +} + +TextualServices::TextualServices(rtl::OUString const & uri): + uri_(uri), data_(new Data) +{ + try { + Parser(uri, data_); + } catch (css::container::NoSuchElementException &) { + throw css::registry::InvalidRegistryException( + (uri + + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM(": no such file"))), + css::uno::Reference< css::uno::XInterface >()); + } +} + +TextualServices::~TextualServices() {} + +css::uno::Reference< css::registry::XRegistryKey > TextualServices::getRootKey() +{ + return new Key(data_, std::vector< rtl::OUString >()); +} + +} } diff --git a/stoc/source/simpleregistry/textualservices.hxx b/stoc/source/simpleregistry/textualservices.hxx new file mode 100644 index 000000000000..0261e260444e --- /dev/null +++ b/stoc/source/simpleregistry/textualservices.hxx @@ -0,0 +1,67 @@ +/************************************************************************* +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +* +************************************************************************/ + +#ifndef INCLUDED_STOC_SOURCE_SIMPLEREGISTRY_TEXTUALSERVICES_HXX +#define INCLUDED_STOC_SOURCE_SIMPLEREGISTRY_TEXTUALSERVICES_HXX + +#include "sal/config.h" + +#include <memory> + +#include "boost/noncopyable.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "rtl/ref.hxx" +#include "rtl/ustring.hxx" + +namespace com { namespace sun { namespace star { namespace registry { + class XRegistryKey; +} } } } + +namespace stoc { namespace simpleregistry { + +class Data; + +class TextualServices: private boost::noncopyable { +public: + explicit TextualServices(rtl::OUString const & uri); + // throws com::sun::star::registry::InvalidRegistryException + + virtual ~TextualServices(); + + inline rtl::OUString getUri() { return uri_; } + + com::sun::star::uno::Reference< com::sun::star::registry::XRegistryKey > + getRootKey(); + +private: + rtl::OUString uri_; + rtl::Reference< Data > data_; +}; + +} } + +#endif diff --git a/stoc/source/stocservices/makefile.mk b/stoc/source/stocservices/makefile.mk new file mode 100644 index 000000000000..2d2444f8a996 --- /dev/null +++ b/stoc/source/stocservices/makefile.mk @@ -0,0 +1,49 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME= stoc +TARGET = stocservices +ENABLE_EXCEPTIONS=TRUE +COMP1TYPELIST = stocserv + +# --- openoffice.org.orig/Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# ------------------------------------------------------------------ + +.INCLUDE : ..$/cppumaker.mk + +# --- openoffice.org.orig/Files ------------------------------------------------------ + +SLOFILES= \ + $(SLO)$/stocservices.obj + +# --- openoffice.org.orig/Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/stoc/source/stocservices/stocserv.xml b/stoc/source/stocservices/stocserv.xml new file mode 100644 index 000000000000..73de7da1bd54 --- /dev/null +++ b/stoc/source/stocservices/stocserv.xml @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd"> +<module-description xmlns:xlink="http://www.w3.org/1999/xlink"> + <module-name> stocservices.uno </module-name> + <component-description> + <author> Daniel Boelzle </author> + <name> com.sun.star.comp.stoc.TypeConverter </name> + <description> +This service provide a widening converter. This means it can convert +from one type to another if possible. +</description> + <loader-name> com.sun.star.loader.SharedLibrary </loader-name> + <language> C++ </language> + <status value="final"/> + <supported-service> com.sun.star.script.Converter </supported-service> + <type> com.sun.star.reflection.FieldAccessMode </type> + <type> com.sun.star.lang.IllegalArgumentException </type> + <type> com.sun.star.lang.XEventListener </type> + <type> com.sun.star.lang.XTypeProvider </type> + <type> com.sun.star.lang.XServiceInfo </type> + <type> com.sun.star.lang.XSingleServiceFactory </type> + <type> com.sun.star.lang.XSingleComponentFactory </type> + <type> com.sun.star.lang.XMultiServiceFactory </type> + <type> com.sun.star.registry.XRegistryKey </type> + <type> com.sun.star.script.XTypeConverter </type> + <type> com.sun.star.script.FailReason </type> + <type> com.sun.star.container.XSet </type> + <type> com.sun.star.container.XNameContainer </type> + <type> com.sun.star.container.XIndexContainer </type> + <type> com.sun.star.uno.XAggregation </type> + <type> com.sun.star.uno.XWeak </type> + <type> com.sun.star.uno.TypeClass </type> + <type> com.sun.star.uno.XComponentContext </type> + </component-description> + <component-description> + <author>Stephan Bergmann</author> + <name>com.sun.star.comp.uri.ExternalUriReferenceTranslator</name> + <description> + Instances of this service translate between external and internal + URI references. + </description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>C++</language> + <status value="under_construction"/> + <supported-service> + com.sun.star.uri.ExternalUriReferenceTranslator + </supported-service> + </component-description> + <component-description> + <author>Stephan Bergmann</author> + <name>com.sun.star.comp.uri.UriReferenceFactory</name> + <description> + Instances of this service create URI references. + </description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>C++</language> + <status value="under_construction"/> + <supported-service> + com.sun.star.uri.UriReferenceFactory + </supported-service> + </component-description> + <component-description> + <author>Stephan Bergmann</author> + <name> + com.sun.star.comp.uri.UriSchemeParser_vndDOTsunDOTstarDOTscript + </name> + <description> + Instances of this service parse textual representations of absolute + “vnd.sun.star.script” URLs. + </description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>C++</language> + <status value="under_construction"/> + <supported-service> + com.sun.star.uri.UriSchemeParser_vndDOTsunDOTstarDOTscript + </supported-service> + </component-description> + <component-description> + <author>Stephan Bergmann</author> + <name>com.sun.star.comp.uri.VndSunStarPkgUrlReferenceFactory</name> + <description> + Instances of this service create “vnd.sun.star.pkg” + URL references. + </description> + <loader-name>com.sun.star.loader.SharedLibrary</loader-name> + <language>C++</language> + <status value="under_construction"/> + <supported-service> + com.sun.star.uri.VndSunStarPkgUrlReferenceFactory + </supported-service> + </component-description> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> sal </project-build-dependency> + <runtime-module-dependency> cppuhelper2(COM) </runtime-module-dependency> + <runtime-module-dependency> cppu2 </runtime-module-dependency> + <runtime-module-dependency> sal2 </runtime-module-dependency> +</module-description> diff --git a/stoc/source/stocservices/stocservices.cxx b/stoc/source/stocservices/stocservices.cxx new file mode 100644 index 000000000000..6270d508eb37 --- /dev/null +++ b/stoc/source/stocservices/stocservices.cxx @@ -0,0 +1,111 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include "stocservices.hxx" + +#include "cppuhelper/factory.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "sal/types.h" +#include "uno/environment.h" +#include "uno/lbnames.h" + +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace cppu; +using namespace osl; +using namespace rtl; +using namespace stoc_services; + +rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT; + +static struct ImplementationEntry g_entries[] = +{ + // typeconv + { + TypeConverter_Impl_CreateInstance, tcv_getImplementationName, + tcv_getSupportedServiceNames, createSingleComponentFactory, + &g_moduleCount.modCnt , 0 + }, + // uriproc + { + ExternalUriReferenceTranslator::create, + ExternalUriReferenceTranslator::getImplementationName, + ExternalUriReferenceTranslator::getSupportedServiceNames, + createSingleComponentFactory, 0, 0 + }, + { + UriReferenceFactory::create, + UriReferenceFactory::getImplementationName, + UriReferenceFactory::getSupportedServiceNames, + createSingleComponentFactory, 0, 0 + }, + { + UriSchemeParser_vndDOTsunDOTstarDOTexpand::create, + UriSchemeParser_vndDOTsunDOTstarDOTexpand::getImplementationName, + UriSchemeParser_vndDOTsunDOTstarDOTexpand::getSupportedServiceNames, + createSingleComponentFactory, 0, 0 + }, + { + UriSchemeParser_vndDOTsunDOTstarDOTscript::create, + UriSchemeParser_vndDOTsunDOTstarDOTscript::getImplementationName, + UriSchemeParser_vndDOTsunDOTstarDOTscript::getSupportedServiceNames, + createSingleComponentFactory, 0, 0 + }, + { + VndSunStarPkgUrlReferenceFactory::create, + VndSunStarPkgUrlReferenceFactory::getImplementationName, + VndSunStarPkgUrlReferenceFactory::getSupportedServiceNames, + createSingleComponentFactory, 0, 0 + }, + { 0, 0, 0, 0, 0, 0 } +}; + +extern "C" +{ + +sal_Bool SAL_CALL component_canUnload( TimeValue *pTime ) +{ + return g_moduleCount.canUnload( &g_moduleCount , pTime ); +} + +//================================================================================================== +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} +//================================================================================================== +void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) +{ + return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries ); +} + +} diff --git a/stoc/source/tdmanager/lrucache.hxx b/stoc/source/tdmanager/lrucache.hxx new file mode 100644 index 000000000000..fadc0a59b7bf --- /dev/null +++ b/stoc/source/tdmanager/lrucache.hxx @@ -0,0 +1,247 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _LRU_CACHE_HXX_ +#define _LRU_CACHE_HXX_ + +// __CACHE_DIAGNOSE forces cache size to 4 and works only for OUString keys +// #define __CACHE_DIAGNOSE 1 + +#include <osl/mutex.hxx> +#include "rtl/ustring.hxx" + +#include <hash_map> + + +/** Implementation of a least recently used (lru) cache. + <br> + @author Daniel Boelzle +*/ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +class LRU_Cache +{ + struct CacheEntry + { + t_Key aKey; + t_Val aVal; + CacheEntry * pPred; + CacheEntry * pSucc; + }; + typedef ::std::hash_map< t_Key, CacheEntry *, t_KeyHash, t_KeyEqual > t_Key2Element; + + mutable ::osl::Mutex _aCacheMutex; + sal_Int32 _nCachedElements; + t_Key2Element _aKey2Element; + + CacheEntry * _pBlock; + mutable CacheEntry * _pHead; + mutable CacheEntry * _pTail; + inline void toFront( CacheEntry * pEntry ) const; + +public: + /** Constructor: + <br> + @param nCachedElements number of elements to be cached; default param set to 128 + */ + inline LRU_Cache( sal_Int32 nCachedElements = 128 ); + /** Destructor: releases all cached elements and keys. + <br> + */ + inline ~LRU_Cache(); + + /** Retrieves a value from the cache. Returns default constructed value, + if none was found. + <br> + @param rKey a key + @return value + */ + inline t_Val getValue( t_Key const & rKey ) const; + /** Sets a value to be cached for given key. + <br> + @param rKey a key + @param rValue a value + */ + inline void setValue( t_Key const & rKey, t_Val const & rValue ); + /** Tests whether a value is cached for given key. + <br> + @param rKey a key + @return true, if value is cached + */ + inline sal_Bool hasValue( t_Key const & rKey ) const; + /** Clears the cache, thus releasing all cached elements and keys. + <br> + */ + inline void clear(); +}; +//__________________________________________________________________________________________________ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +inline LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::LRU_Cache( sal_Int32 nCachedElements ) +#ifdef __CACHE_DIAGNOSE + : _nCachedElements( 4 ) +#else + : _nCachedElements( nCachedElements ) +#endif + , _pBlock( 0 ) +{ + if (_nCachedElements > 0) + { + _pBlock = new CacheEntry[_nCachedElements]; + _pHead = _pBlock; + _pTail = _pBlock + _nCachedElements -1; + for ( sal_Int32 nPos = _nCachedElements; nPos--; ) + { + _pBlock[nPos].pPred = _pBlock + nPos -1; + _pBlock[nPos].pSucc = _pBlock + nPos +1; + } + } +} +//__________________________________________________________________________________________________ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +inline LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::~LRU_Cache() +{ + delete [] _pBlock; +} +//__________________________________________________________________________________________________ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +inline void LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::toFront( + CacheEntry * pEntry ) const +{ + if (pEntry != _pHead) + { + // cut out element + if (pEntry == _pTail) + { + _pTail = pEntry->pPred; + } + else + { + pEntry->pSucc->pPred = pEntry->pPred; + pEntry->pPred->pSucc = pEntry->pSucc; + } + // push to front + _pHead->pPred = pEntry; + pEntry->pSucc = _pHead; + _pHead = pEntry; + } +} +//__________________________________________________________________________________________________ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +inline sal_Bool LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::hasValue( + t_Key const & rKey ) const +{ + ::osl::MutexGuard aGuard( _aCacheMutex ); + typename t_Key2Element::const_iterator const iFind( _aKey2Element.find( rKey ) ); + return (iFind != _aKey2Element.end()); +} +//__________________________________________________________________________________________________ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +inline t_Val LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::getValue( + t_Key const & rKey ) const +{ + ::osl::MutexGuard aGuard( _aCacheMutex ); + const typename t_Key2Element::const_iterator iFind( _aKey2Element.find( rKey ) ); + if (iFind != _aKey2Element.end()) + { + CacheEntry * pEntry = (*iFind).second; + toFront( pEntry ); +#ifdef __CACHE_DIAGNOSE + OSL_TRACE( "> retrieved element \"" ); + OSL_TRACE( ::rtl::OUStringToOString( pEntry->aKey, RTL_TEXTENCODING_ASCII_US ).getStr() ); + OSL_TRACE( "\" from cache <\n" ); +#endif + return pEntry->aVal; + } + return t_Val(); +} +//__________________________________________________________________________________________________ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +inline void LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::setValue( + t_Key const & rKey, t_Val const & rValue ) +{ + if (_nCachedElements > 0) + { + ::osl::MutexGuard aGuard( _aCacheMutex ); + typename t_Key2Element::const_iterator const iFind( _aKey2Element.find( rKey ) ); + + CacheEntry * pEntry; + if (iFind == _aKey2Element.end()) + { + pEntry = _pTail; // erase last element +#ifdef __CACHE_DIAGNOSE + if (pEntry->aKey.getLength()) + { + OSL_TRACE( "> kicking element \"" ); + OSL_TRACE( ::rtl::OUStringToOString( pEntry->aKey, RTL_TEXTENCODING_ASCII_US ).getStr() ); + OSL_TRACE( "\" from cache <\n" ); + } +#endif + _aKey2Element.erase( pEntry->aKey ); + _aKey2Element[ pEntry->aKey = rKey ] = pEntry; + } + else + { + pEntry = (*iFind).second; +#ifdef __CACHE_DIAGNOSE + OSL_TRACE( "> replacing element \"" ); + OSL_TRACE( ::rtl::OUStringToOString( pEntry->aKey, RTL_TEXTENCODING_ASCII_US ).getStr() ); + OSL_TRACE( "\" in cache <\n" ); +#endif + } + pEntry->aVal = rValue; + toFront( pEntry ); + } +} +//__________________________________________________________________________________________________ +template< class t_Key, class t_Val, class t_KeyHash, class t_KeyEqual > +inline void LRU_Cache< t_Key, t_Val, t_KeyHash, t_KeyEqual >::clear() +{ + ::osl::MutexGuard aGuard( _aCacheMutex ); + _aKey2Element.clear(); + for ( sal_Int32 nPos = _nCachedElements; nPos--; ) + { + _pBlock[nPos].aKey = t_Key(); + _pBlock[nPos].aVal = t_Val(); + } +#ifdef __CACHE_DIAGNOSE + OSL_TRACE( "> cleared cache <\n" ); +#endif +} + +//================================================================================================== +struct FctHashOUString : public ::std::unary_function< ::rtl::OUString const &, size_t > +{ + size_t operator()( ::rtl::OUString const & rKey ) const + { return (size_t)rKey.hashCode(); } +}; + +/** Template instance for OUString keys, Any values.<br> +*/ +typedef LRU_Cache< ::rtl::OUString, ::com::sun::star::uno::Any, + FctHashOUString, ::std::equal_to< ::rtl::OUString > > + LRU_CacheAnyByOUString; + + +#endif diff --git a/stoc/source/tdmanager/makefile.mk b/stoc/source/tdmanager/makefile.mk new file mode 100644 index 000000000000..dbc4e762afff --- /dev/null +++ b/stoc/source/tdmanager/makefile.mk @@ -0,0 +1,49 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME= stoc +TARGET = typemgr +ENABLE_EXCEPTIONS=TRUE +BOOTSTRAP_SERVICE=TRUE +UNOUCROUT= $(OUT)$/inc$/bootstrap + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# ------------------------------------------------------------------ + +SLOFILES= \ + $(SLO)$/tdmgr.obj \ + $(SLO)$/tdmgr_check.obj \ + $(SLO)$/tdmgr_tdenumeration.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/stoc/source/tdmanager/tdmgr.cxx b/stoc/source/tdmanager/tdmgr.cxx new file mode 100644 index 000000000000..390881bb0d1d --- /dev/null +++ b/stoc/source/tdmanager/tdmgr.cxx @@ -0,0 +1,1163 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include <osl/diagnose.h> +#include <osl/mutex.hxx> +#include "rtl/ustrbuf.hxx" +#include <cppuhelper/factory.hxx> +#ifndef _CPPUHELPER_IMPLBASE5_HXX_ +#include <cppuhelper/compbase5.hxx> +#endif +#include <cppuhelper/implbase1.hxx> +#ifndef _CPPUHELPER_IMPLEMENTATIONENTRY_HXX_ +#include <cppuhelper/implementationentry.hxx> +#endif +#include "tdmgr_common.hxx" +#include "tdmgr_tdenumeration.hxx" +#include "lrucache.hxx" + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/lang/XEventListener.hpp> +#include <com/sun/star/lang/XTypeProvider.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/container/XSet.hpp> +#include <com/sun/star/container/XContentEnumerationAccess.hpp> +#include <com/sun/star/reflection/XTypeDescription.hpp> +#include <com/sun/star/reflection/XArrayTypeDescription.hpp> +#include <com/sun/star/reflection/XIndirectTypeDescription.hpp> +#include <com/sun/star/reflection/XInterfaceTypeDescription.hpp> +#include "com/sun/star/reflection/XStructTypeDescription.hpp" +#include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include "com/sun/star/uno/RuntimeException.hpp" + +#include <algorithm> +#include <vector> + +using namespace std; +using namespace cppu; +using namespace rtl; +using namespace osl; +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::reflection; +using namespace com::sun::star::container; +using namespace com::sun::star::registry; + + + +static const sal_Int32 CACHE_SIZE = 512; + +#define SERVICENAME "com.sun.star.reflection.TypeDescriptionManager" +#define IMPLNAME "com.sun.star.comp.stoc.TypeDescriptionManager" + +//-------------------------------------------------------------------------------------------------- +// exported via tdmgr_common.hxx +extern rtl_StandardModuleCount g_moduleCount; + +namespace stoc_bootstrap +{ +Sequence< OUString > SAL_CALL tdmgr_getSupportedServiceNames() +{ + static Sequence < OUString > *pNames = 0; + if( ! pNames ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( !pNames ) + { + static Sequence< OUString > seqNames(1); + seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME)); + pNames = &seqNames; + } + } + return *pNames; +} + +OUString SAL_CALL tdmgr_getImplementationName() +{ + static OUString *pImplName = 0; + if( ! pImplName ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( ! pImplName ) + { + static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) ); + pImplName = &implName; + } + } + return *pImplName; +} +} + +namespace stoc_tdmgr +{ +typedef vector< Reference< XHierarchicalNameAccess > > ProviderVector; + +class EnumerationImpl; +class ManagerImpl; + +//================================================================================================== +class EventListenerImpl : public ImplHelper1< XEventListener > +{ + ManagerImpl * _pMgr; + +public: + EventListenerImpl( ManagerImpl * pMgr ) + : _pMgr( pMgr ) + { + ::g_moduleCount.modCnt.acquire( &::g_moduleCount.modCnt ); + } + virtual ~EventListenerImpl(); + + // lifetime delegated to manager + virtual void SAL_CALL acquire() throw(); + virtual void SAL_CALL release() throw(); + + // XEventListener + virtual void SAL_CALL disposing( const EventObject & rEvt ) throw(::com::sun::star::uno::RuntimeException); +}; + +EventListenerImpl::~EventListenerImpl() +{ + ::g_moduleCount.modCnt.release( &::g_moduleCount.modCnt ); +} + +//================================================================================================== +class ManagerImpl + : public WeakComponentImplHelper5< XServiceInfo, + XSet, + XHierarchicalNameAccess, + XTypeDescriptionEnumerationAccess, + XInitialization > +{ + friend class EnumerationImpl; + friend class EventListenerImpl; + + Mutex _aComponentMutex; + Reference< XComponentContext > _xContext; + EventListenerImpl _aEventListener; + + // elements + sal_Bool _bCaching; + LRU_CacheAnyByOUString _aElements; + // provider chain + ProviderVector _aProviders; + + inline Any getSimpleType( const OUString & rName ); + + Reference< XTypeDescription > getInstantiatedStruct(OUString const & name); + +protected: + virtual void SAL_CALL disposing(); + +public: + ManagerImpl( Reference< XComponentContext > const & xContext, sal_Int32 nCacheSize ); + virtual ~ManagerImpl(); + + // XInitialization + virtual void SAL_CALL initialize( const Sequence< Any > & args ) throw (Exception, RuntimeException); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw(::com::sun::star::uno::RuntimeException); + + // XElementAccess + virtual Type SAL_CALL getElementType() throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasElements() throw(::com::sun::star::uno::RuntimeException); + + // XEnumerationAccess + virtual Reference< XEnumeration > SAL_CALL createEnumeration() throw(::com::sun::star::uno::RuntimeException); + + // XSet + virtual sal_Bool SAL_CALL has( const Any & rElement ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL insert( const Any & rElement ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL remove( const Any & rElement ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException); + + // XHierarchicalNameAccess + virtual Any SAL_CALL getByHierarchicalName( const OUString & rName ) throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasByHierarchicalName( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException); + + // XTypeDescriptionEnumerationAccess + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::reflection::XTypeDescriptionEnumeration > SAL_CALL + createTypeDescriptionEnumeration( + const ::rtl::OUString& moduleName, + const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::TypeClass >& types, + ::com::sun::star::reflection::TypeDescriptionSearchDepth depth ) + throw ( ::com::sun::star::reflection::NoSuchTypeNameException, + ::com::sun::star::reflection::InvalidTypeNameException, + ::com::sun::star::uno::RuntimeException ); +}; + +//================================================================================================== +class EnumerationImpl + : public WeakImplHelper1< XEnumeration > +{ + ManagerImpl * _pMgr; + size_t _nPos; + +public: + EnumerationImpl( ManagerImpl * pManager ); + virtual ~EnumerationImpl(); + + // XEnumeration + virtual sal_Bool SAL_CALL hasMoreElements() throw(::com::sun::star::uno::RuntimeException); + virtual Any SAL_CALL nextElement() throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException); +}; + +//################################################################################################## + +// lifetime delegated to manager +//__________________________________________________________________________________________________ +void EventListenerImpl::acquire() throw() +{ + _pMgr->acquire(); +} +//__________________________________________________________________________________________________ +void EventListenerImpl::release() throw() +{ + _pMgr->release(); +} + +// XEventListener +//__________________________________________________________________________________________________ +void EventListenerImpl::disposing( const EventObject & rEvt ) + throw(::com::sun::star::uno::RuntimeException) +{ + _pMgr->remove( makeAny( rEvt.Source ) ); +} + +//################################################################################################## + +//__________________________________________________________________________________________________ +EnumerationImpl::EnumerationImpl( ManagerImpl * pManager ) + : _pMgr( pManager ) + , _nPos( 0 ) +{ + _pMgr->acquire(); +} +//__________________________________________________________________________________________________ +EnumerationImpl::~EnumerationImpl() +{ + _pMgr->release(); +} + +// XEnumeration +//__________________________________________________________________________________________________ +sal_Bool EnumerationImpl::hasMoreElements() + throw(::com::sun::star::uno::RuntimeException) +{ + MutexGuard aGuard( _pMgr->_aComponentMutex ); + return (_nPos < _pMgr->_aProviders.size()); +} +//__________________________________________________________________________________________________ +Any EnumerationImpl::nextElement() + throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) +{ + MutexGuard aGuard( _pMgr->_aComponentMutex ); + if (_nPos >= _pMgr->_aProviders.size()) + { + throw NoSuchElementException( + OUString( RTL_CONSTASCII_USTRINGPARAM("there is no further element!") ), + (XWeak *)(OWeakObject *)this ); + } + return makeAny( _pMgr->_aProviders[_nPos++] ); +} + +//################################################################################################## + +//__________________________________________________________________________________________________ +ManagerImpl::ManagerImpl( + Reference< XComponentContext > const & xContext, sal_Int32 nCacheSize ) + : WeakComponentImplHelper5< + XServiceInfo, XSet, XHierarchicalNameAccess, + XTypeDescriptionEnumerationAccess, XInitialization >( _aComponentMutex ) + , _xContext( xContext ) + , _aEventListener( this ) + , _bCaching( sal_True ) + , _aElements( nCacheSize ) +{ + ::g_moduleCount.modCnt.acquire( &::g_moduleCount.modCnt ); +} +//__________________________________________________________________________________________________ +ManagerImpl::~ManagerImpl() +{ + OSL_ENSURE( _aProviders.size() == 0, "### still providers left!" ); + OSL_TRACE( "> TypeDescriptionManager shut down. <\n" ); + ::g_moduleCount.modCnt.release( &::g_moduleCount.modCnt ); +} +//__________________________________________________________________________________________________ +void ManagerImpl::disposing() +{ + // called on disposing the tdmgr instance (supposedly from context) + _bCaching = sal_False; + _aElements.clear(); + _xContext.clear(); + _aProviders.clear(); +} + +// XInitialization +//__________________________________________________________________________________________________ +void ManagerImpl::initialize( + const Sequence< Any > & args ) + throw (Exception, RuntimeException) +{ + // additional providers + Any const * pProviders = args.getConstArray(); + for ( sal_Int32 nPos = 0; nPos < args.getLength(); ++nPos ) + { + Reference< XHierarchicalNameAccess > xHA( pProviders[ nPos ], UNO_QUERY ); + OSL_ENSURE( xHA.is(), "### no td provider!" ); + + if (xHA.is()) + { + try + { + insert( makeAny( xHA ) ); + } + catch (IllegalArgumentException &) + { + } + catch (ElementExistException &) + { + } + } + } +} + +// XServiceInfo +//__________________________________________________________________________________________________ +OUString ManagerImpl::getImplementationName() + throw(::com::sun::star::uno::RuntimeException) +{ + return stoc_bootstrap::tdmgr_getImplementationName(); +} +//__________________________________________________________________________________________________ +sal_Bool ManagerImpl::supportsService( const OUString & rServiceName ) + throw(::com::sun::star::uno::RuntimeException) +{ + const Sequence< OUString > & rSNL = getSupportedServiceNames(); + const OUString * pArray = rSNL.getConstArray(); + for ( sal_Int32 nPos = rSNL.getLength(); nPos--; ) + { + if (pArray[nPos] == rServiceName) + return sal_True; + } + return sal_False; +} +//__________________________________________________________________________________________________ +Sequence< OUString > ManagerImpl::getSupportedServiceNames() + throw(::com::sun::star::uno::RuntimeException) +{ + return stoc_bootstrap::tdmgr_getSupportedServiceNames(); +} + +// XElementAccess +//__________________________________________________________________________________________________ +Type ManagerImpl::getElementType() + throw(::com::sun::star::uno::RuntimeException) +{ + return ::getCppuType( (const Reference< XHierarchicalNameAccess > *)0 ); +} +//__________________________________________________________________________________________________ +sal_Bool ManagerImpl::hasElements() + throw(::com::sun::star::uno::RuntimeException) +{ + MutexGuard aGuard( _aComponentMutex ); + return (_aProviders.size() > 0); +} + +// XEnumerationAccess +//__________________________________________________________________________________________________ +Reference< XEnumeration > ManagerImpl::createEnumeration() + throw(::com::sun::star::uno::RuntimeException) +{ + return new EnumerationImpl( this ); +} + +// XSet +//__________________________________________________________________________________________________ +sal_Bool SAL_CALL ManagerImpl::has( const Any & rElement ) + throw(::com::sun::star::uno::RuntimeException) +{ + Reference< XHierarchicalNameAccess > xElem; + if (rElement >>= xElem) + { + MutexGuard aGuard( _aComponentMutex ); + return (find( _aProviders.begin(), _aProviders.end(), xElem ) != _aProviders.end()); + } + return sal_False; +} + +//__________________________________________________________________________________________________ +void SAL_CALL ManagerImpl::insert( const Any & rElement ) + throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException) +{ + Reference< XHierarchicalNameAccess > xElem; + if (! (rElement >>= xElem) || !xElem.is()) + { + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no valid type description provider given!") ), + (XWeak *)(OWeakObject *)this, 0 ); + } + + MutexGuard aGuard( _aComponentMutex ); + if (find( _aProviders.begin(), _aProviders.end(), xElem ) != _aProviders.end()) + { + throw ElementExistException( + OUString( RTL_CONSTASCII_USTRINGPARAM("provider already inserted!") ), + (XWeak *)(OWeakObject *)this ); + } + + if (! _aProviders.empty()) + { + // check whether all types are compatible, if possible: + Reference<reflection::XTypeDescriptionEnumerationAccess> xTDEnumAccess( + xElem, UNO_QUERY ); + OSL_ENSURE( xTDEnumAccess.is(), + "### providers ought to implement " + "reflection::XTypeDescriptionEnumerationAccess!" ); + if (xTDEnumAccess.is()) + { + try + { + TypeClass ar [] = { + TypeClass_ENUM, TypeClass_TYPEDEF, TypeClass_SEQUENCE, + TypeClass_STRUCT, TypeClass_EXCEPTION, + /* TypeClass_UNION, TypeClass_ARRAY not supported */ + TypeClass_INTERFACE, + TypeClass_SERVICE, + TypeClass_INTERFACE_METHOD, TypeClass_INTERFACE_ATTRIBUTE, + TypeClass_PROPERTY, TypeClass_CONSTANT, TypeClass_CONSTANTS, + TypeClass_SINGLETON + }; + Reference<reflection::XTypeDescriptionEnumeration> xTDEnum( + xTDEnumAccess->createTypeDescriptionEnumeration( + OUString() /* all modules */, + Sequence<TypeClass>( ar, ARLEN(ar) ), + reflection::TypeDescriptionSearchDepth_INFINITE ) ); + + while (xTDEnum->hasMoreElements()) + { + Reference<reflection::XTypeDescription> xNewTD; + try + { + xNewTD = xTDEnum->nextTypeDescription(); + } + catch (container::NoSuchElementException & exc) + { + throw lang::IllegalArgumentException( + OUSTR("NoSuchElementException occured: ") + + exc.Message, static_cast<OWeakObject *>(this), + -1 /* unknown */ ); + } + + try + { + OUString newName( xNewTD->getName() ); + Reference<reflection::XTypeDescription> xExistingTD( + getByHierarchicalName( newName ), UNO_QUERY ); + OSL_ASSERT( xExistingTD.is() ); + // existing, check whether compatible: + if (xExistingTD.is()) + { + try + { + check( xNewTD, xExistingTD ); + } + catch (IncompatibleTypeException & exc) + { + throw lang::IllegalArgumentException( + OUSTR("Rejecting types due to " + "incompatibility! ") + exc.m_cause, + static_cast<OWeakObject *>(this), 0 ); + } + } + } + catch (container::NoSuchElementException &) + { + // type not in: ok + } + } + } + catch (reflection::NoSuchTypeNameException & exc) + { + throw lang::IllegalArgumentException( + OUSTR("NoSuchTypeNameException occured: ") + exc.Message, + static_cast<OWeakObject *>(this), -1 /* unknown */ ); + } + catch (reflection::InvalidTypeNameException & exc) + { + throw lang::IllegalArgumentException( + OUSTR("InvalidTypeNameException occured: ") + exc.Message, + static_cast<OWeakObject *>(this), -1 /* unknown */ ); + } + } + } + + _aProviders.push_back( xElem ); + Reference< XComponent > xComp( xElem, UNO_QUERY ); + if (xComp.is()) + xComp->addEventListener( &_aEventListener ); +} +//__________________________________________________________________________________________________ +void SAL_CALL ManagerImpl::remove( const Any & rElement ) + throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException) +{ + if (!rBHelper.bDisposed && !rBHelper.bInDispose) + { + Reference< XHierarchicalNameAccess > xElem; + if (! (rElement >>= xElem)) + { + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("no type description provider given!") ), + (XWeak *)(OWeakObject *)this, 0 ); + } + + MutexGuard aGuard( _aComponentMutex ); + ProviderVector::iterator iFind( find( _aProviders.begin(), _aProviders.end(), xElem ) ); + if (iFind == _aProviders.end()) + { + throw NoSuchElementException( + OUString( RTL_CONSTASCII_USTRINGPARAM("provider not found!") ), + (XWeak *)(OWeakObject *)this ); + } + _aProviders.erase( iFind ); + } + + Reference< XComponent > xComp; + if (rElement >>= xComp) + xComp->removeEventListener( &_aEventListener ); +} + +// XTypeDescriptionEnumerationAccess +//__________________________________________________________________________________________________ +// virtual +Reference< XTypeDescriptionEnumeration > SAL_CALL +ManagerImpl::createTypeDescriptionEnumeration( + const OUString & moduleName, + const Sequence< TypeClass > & types, + TypeDescriptionSearchDepth depth ) + throw ( NoSuchTypeNameException, + InvalidTypeNameException, + RuntimeException ) +{ + MutexGuard aGuard( _aComponentMutex ); + + TDEnumerationAccessStack aStack; + ProviderVector::const_iterator it = _aProviders.begin(); + const ProviderVector::const_iterator end = _aProviders.end(); + while ( it != end ) + { + Reference< XTypeDescriptionEnumerationAccess >xEnumAccess( + (*it), UNO_QUERY ); + OSL_ENSURE( xEnumAccess.is(), + "### no XTypeDescriptionEnumerationAccess!" ); + if ( xEnumAccess.is() ) + aStack.push( xEnumAccess ); + + it++; + } + + return Reference< XTypeDescriptionEnumeration >( + new TypeDescriptionEnumerationImpl( moduleName, + types, + depth, + aStack ) ); +} + + +//################################################################################################## +//################################################################################################## +//################################################################################################## + + +//================================================================================================== +class SimpleTypeDescriptionImpl + : public WeakImplHelper1< XTypeDescription > +{ + TypeClass _eTC; + OUString _aName; + +public: + SimpleTypeDescriptionImpl( TypeClass eTC, const OUString & rName ) + : _eTC( eTC ) + , _aName( rName ) + {} + + // XTypeDescription + virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException); + virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); +}; + +// XTypeDescription +//__________________________________________________________________________________________________ +TypeClass SimpleTypeDescriptionImpl::getTypeClass() + throw(::com::sun::star::uno::RuntimeException) +{ + return _eTC; +} +//__________________________________________________________________________________________________ +OUString SimpleTypeDescriptionImpl::getName() + throw(::com::sun::star::uno::RuntimeException) +{ + return _aName; +} + +//================================================================================================== +class SequenceTypeDescriptionImpl + : public WeakImplHelper1< XIndirectTypeDescription > +{ + Reference< XTypeDescription > _xElementTD; + +public: + SequenceTypeDescriptionImpl( const Reference< XTypeDescription > & xElementTD ) + : _xElementTD( xElementTD ) + {} + + // XTypeDescription + virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException); + virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); + + // XIndirectTypeDescription + virtual Reference< XTypeDescription > SAL_CALL getReferencedType() throw(::com::sun::star::uno::RuntimeException); +}; + +// XTypeDescription +//__________________________________________________________________________________________________ +TypeClass SequenceTypeDescriptionImpl::getTypeClass() + throw(::com::sun::star::uno::RuntimeException) +{ + return TypeClass_SEQUENCE; +} +//__________________________________________________________________________________________________ +OUString SequenceTypeDescriptionImpl::getName() + throw(::com::sun::star::uno::RuntimeException) +{ + return (OUString( RTL_CONSTASCII_USTRINGPARAM("[]") ) + _xElementTD->getName()); +} + +// XIndirectTypeDescription +//__________________________________________________________________________________________________ +Reference< XTypeDescription > SequenceTypeDescriptionImpl::getReferencedType() + throw(::com::sun::star::uno::RuntimeException) +{ + return _xElementTD; +} + +//================================================================================================== +class ArrayTypeDescriptionImpl + : public WeakImplHelper1< XArrayTypeDescription > +{ + Reference< XTypeDescription > _xElementTD; + Mutex _aDimensionMutex; + sal_Int32 _nDimensions; + Sequence< sal_Int32 > _seqDimensions; + OUString _sDimensions; + + void initDimensions(const OUString& rSDimensions); +public: + ArrayTypeDescriptionImpl( const Reference< XTypeDescription > & xElementTD, + sal_Int32 nDimensions, const OUString& rSDimensions ) + : _xElementTD( xElementTD ) + , _nDimensions( nDimensions ) + , _seqDimensions( Sequence< sal_Int32 >(nDimensions) ) + , _sDimensions( rSDimensions ) + { + initDimensions( rSDimensions ); + } + virtual ~ArrayTypeDescriptionImpl() {} + + // XTypeDescription + virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException); + virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); + + // XArrayTypeDescription + virtual Reference< XTypeDescription > SAL_CALL getType() throw(::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getNumberOfDimensions() throw(::com::sun::star::uno::RuntimeException); + virtual Sequence< sal_Int32 > SAL_CALL getDimensions() throw(::com::sun::star::uno::RuntimeException); +}; +//__________________________________________________________________________________________________ +static sal_Int32 unicodeToInteger( sal_Int8 base, const sal_Unicode *s ) +{ + sal_Int32 r = 0; + sal_Int32 negative = 0; + + if (*s == '-') + { + negative = 1; + s++; + } + if (base == 8 && *s == '0') + s++; + else if (base == 16 && *s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X')) + s += 2; + + for (; *s; s++) + { + if (*s <= '9' && *s >= '0') + r = (r * base) + (*s - '0'); + else if (base > 10 && *s <= 'f' && *s >= 'a') + r = (r * base) + (*s - 'a' + 10); + else if (base > 10 && *s <= 'F' && *s >= 'A') + r = (r * base) + (*s - 'A' + 10); + else + break; + } + if (negative) r *= -1; + return r; +} +//__________________________________________________________________________________________________ +void ArrayTypeDescriptionImpl::initDimensions(const OUString& rSDimensions) +{ + MutexGuard aGuard( _aDimensionMutex ); + + sal_Int32 * pDimensions = _seqDimensions.getArray(); + OUString tmp(rSDimensions); + sal_Unicode* p = (sal_Unicode*)tmp.getStr()+1; + sal_Unicode* pOffset = p; + sal_Int32 len = tmp.getLength() - 1 ; + sal_Int32 i = 0; + + while ( len > 0) + { + pOffset++; + if (*pOffset == ']') + { + *pOffset = '\0'; + pOffset += 2; + len -= 3; + pDimensions[i++] = unicodeToInteger(10, p); + p = pOffset; + } else + len--; + } +} + +// XTypeDescription +//__________________________________________________________________________________________________ +TypeClass ArrayTypeDescriptionImpl::getTypeClass() + throw(::com::sun::star::uno::RuntimeException) +{ + return TypeClass_ARRAY; +} +//__________________________________________________________________________________________________ +OUString ArrayTypeDescriptionImpl::getName() + throw(::com::sun::star::uno::RuntimeException) +{ + return (_xElementTD->getName() + _sDimensions); +} + +// XArrayTypeDescription +//__________________________________________________________________________________________________ +Reference< XTypeDescription > ArrayTypeDescriptionImpl::getType() + throw(::com::sun::star::uno::RuntimeException) +{ + return _xElementTD; +} + +//__________________________________________________________________________________________________ +sal_Int32 ArrayTypeDescriptionImpl::getNumberOfDimensions() + throw(::com::sun::star::uno::RuntimeException) +{ + return _nDimensions; +} + +//__________________________________________________________________________________________________ +Sequence< sal_Int32 > ArrayTypeDescriptionImpl::getDimensions() + throw(::com::sun::star::uno::RuntimeException) +{ + return _seqDimensions; +} + +//################################################################################################## +//################################################################################################## +//################################################################################################## + + +//__________________________________________________________________________________________________ +inline Any ManagerImpl::getSimpleType( const OUString & rName ) +{ + Any aRet; + + if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("string") )) + aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_STRING, rName ) ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("long") )) + aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_LONG, rName ) ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("unsigned long") )) + aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_UNSIGNED_LONG, rName ) ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("boolean") )) + aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_BOOLEAN, rName ) ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("char") )) + aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_CHAR, rName ) ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("byte") )) + aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_BYTE, rName ) ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("short") )) + aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_SHORT, rName ) ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("unsigned short") )) + aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_UNSIGNED_SHORT, rName ) ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("hyper") )) + aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_HYPER, rName ) ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("unsigned hyper") )) + aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_UNSIGNED_HYPER, rName ) ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("float") )) + aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_FLOAT, rName ) ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("double") )) + aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_DOUBLE, rName ) ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("any") )) + aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_ANY, rName ) ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("void") )) + aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_VOID, rName ) ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("type") )) + aRet <<= Reference< XTypeDescription >( new SimpleTypeDescriptionImpl( TypeClass_TYPE, rName ) ); + + return aRet; +} + +namespace { + +Reference< XTypeDescription > resolveTypedefs( + Reference< XTypeDescription > const & type) +{ + Reference< XTypeDescription > resolved(type); + while (resolved->getTypeClass() == TypeClass_TYPEDEF) { + resolved = Reference< XIndirectTypeDescription >( + type, UNO_QUERY_THROW)->getReferencedType(); + } + return resolved; +} + +bool isNonVoidNonExceptionType(Reference< XTypeDescription > const & type) { + switch (type->getTypeClass()) { + case TypeClass_BOOLEAN: + case TypeClass_BYTE: + case TypeClass_SHORT: + case TypeClass_UNSIGNED_SHORT: + case TypeClass_LONG: + case TypeClass_UNSIGNED_LONG: + case TypeClass_HYPER: + case TypeClass_UNSIGNED_HYPER: + case TypeClass_FLOAT: + case TypeClass_DOUBLE: + case TypeClass_CHAR: + case TypeClass_STRING: + case TypeClass_TYPE: + case TypeClass_ANY: + case TypeClass_SEQUENCE: + case TypeClass_ENUM: + case TypeClass_STRUCT: + case TypeClass_INTERFACE: + return true; + + default: + return false; + } +} + +class InstantiatedStruct: public WeakImplHelper1< XStructTypeDescription > { +public: + InstantiatedStruct( + Reference< XStructTypeDescription > const & structType, + std::vector< Reference< XTypeDescription > > const & arguments); + + virtual TypeClass SAL_CALL getTypeClass() throw (RuntimeException) + { return TypeClass_STRUCT; } + + virtual OUString SAL_CALL getName() throw (RuntimeException); + + virtual Reference< XTypeDescription > SAL_CALL getBaseType() + throw (RuntimeException) + { return m_struct->getBaseType(); } + + virtual Sequence< Reference< XTypeDescription > > SAL_CALL getMemberTypes() + throw (RuntimeException); + + virtual Sequence< OUString > SAL_CALL getMemberNames() + throw (RuntimeException) + { return m_struct->getMemberNames(); } + + virtual Sequence< OUString > SAL_CALL getTypeParameters() + throw (RuntimeException) + { return Sequence< OUString >(); } + + virtual Sequence< Reference< XTypeDescription > > SAL_CALL + getTypeArguments() throw (RuntimeException) + { return m_arguments; } + +private: + Reference< XStructTypeDescription > m_struct; + Sequence< Reference< XTypeDescription > > m_arguments; +}; + +InstantiatedStruct::InstantiatedStruct( + Reference< XStructTypeDescription > const & structType, + std::vector< Reference< XTypeDescription > > const & arguments): + m_struct(structType), + m_arguments(static_cast< sal_Int32 >(arguments.size())) +{ + for (std::vector< Reference< XTypeDescription > >::size_type i = 0; + i < arguments.size(); ++i) + { + m_arguments[static_cast< sal_Int32 >(i)] = arguments[i]; + } +} + +OUString InstantiatedStruct::getName() throw (RuntimeException) { + OUStringBuffer buf(m_struct->getName()); + buf.append(static_cast< sal_Unicode >('<')); + for (sal_Int32 i = 0; i < m_arguments.getLength(); ++i) { + if (i != 0) { + buf.append(static_cast< sal_Unicode >(',')); + } + buf.append(m_arguments[i]->getName()); + } + buf.append(static_cast< sal_Unicode >('>')); + return buf.makeStringAndClear(); +} + +Sequence< Reference< XTypeDescription > > InstantiatedStruct::getMemberTypes() + throw (RuntimeException) +{ + Sequence< Reference< XTypeDescription > > types(m_struct->getMemberTypes()); + for (sal_Int32 i = 0; i < types.getLength(); ++i) { + if (types[i]->getTypeClass() == TypeClass_UNKNOWN) { + Sequence< OUString > parameters(m_struct->getTypeParameters()); + OSL_ASSERT(parameters.getLength() == m_arguments.getLength()); + for (sal_Int32 j = 0; j < parameters.getLength(); ++j) { + if (parameters[j] == types[i]->getName()) { + types[i] = m_arguments[j]; + break; + } + } + } + } + return types; +} + +} + +Reference< XTypeDescription > ManagerImpl::getInstantiatedStruct( + OUString const & name) +{ + sal_Int32 i = name.indexOf('<'); + OSL_ASSERT(i >= 0); + Reference< XStructTypeDescription > structType( + getByHierarchicalName(name.copy(0, i)), UNO_QUERY); + std::vector< Reference< XTypeDescription > > args; + bool good = structType.is(); + if (good) { + do { + ++i; // skip '<' or ',' + sal_Int32 j = i; + for (sal_Int32 level = 0; j != name.getLength(); ++j) { + sal_Unicode c = name[j]; + if (c == ',') { + if (level == 0) { + break; + } + } else if (c == '<') { + ++level; + } else if (c == '>') { + if (level == 0) { + break; + } + --level; + } + } + if (j != name.getLength()) { + Reference< XTypeDescription > type( + getByHierarchicalName(name.copy(i, j - i)), UNO_QUERY); + if (isNonVoidNonExceptionType(resolveTypedefs(type))) { + args.push_back(type); + } else { + good = false; + break; + } + } + i = j; + } while (i != name.getLength() && name[i] != '>'); + good = good && i == name.getLength() - 1 + && name[i] == '>' && !args.empty(); + } + // args.size() cannot exceed SAL_MAX_INT32, as each argument consumes at + // least one position within an rtl::OUString (which is no longer than + // SAL_MAX_INT32): + if (!good + || (args.size() + != sal::static_int_cast< sal_uInt32 >( + structType->getTypeParameters().getLength()))) + { + throw NoSuchElementException(name, static_cast< OWeakObject * >(this)); + } + return new InstantiatedStruct(structType, args); +} + +// XHierarchicalNameAccess +//__________________________________________________________________________________________________ +Any ManagerImpl::getByHierarchicalName( const OUString & rName ) + throw(::com::sun::star::container::NoSuchElementException, ::com::sun::star::uno::RuntimeException) +{ + Any aRet; + if (_bCaching) + aRet = _aElements.getValue( rName ); + if (rName.getLength() && !aRet.hasValue()) + { + sal_Int32 nIndex; + if (rName[0] == '[') // test for sequence + { + Reference< XTypeDescription > xElemType( + getByHierarchicalName( rName.copy( 2 ) ), + UNO_QUERY_THROW ); + aRet <<= Reference< XTypeDescription >( + new SequenceTypeDescriptionImpl( xElemType ) ); + } + else if (rName[rName.getLength()-1] == ']') // test for array + { + sal_Int32 nIndex2 = 0, nTokens = 0; + do { rName.getToken( 0, '[', nIndex2 ); nTokens++; } while( nIndex2 != -1 ); + sal_Int32 nDims = nTokens - 1; + sal_Int32 dimOffset = rName.indexOf('['); + Reference< XTypeDescription > xElemType( + getByHierarchicalName( rName.copy( 0, dimOffset ) ), + UNO_QUERY_THROW ); + aRet <<= Reference< XTypeDescription >( + new ArrayTypeDescriptionImpl( + xElemType, nDims, rName.copy(dimOffset) ) ); + } + // test for interface member names: + else if ((nIndex = rName.indexOf( ':' )) >= 0) + { + Reference< XInterfaceTypeDescription > xIfaceTD( + getByHierarchicalName( rName.copy( 0, nIndex ) ), + UNO_QUERY_THROW ); + const Sequence< Reference< XInterfaceMemberTypeDescription > > & + rMembers = xIfaceTD->getMembers(); + const Reference< XInterfaceMemberTypeDescription > * pMembers = + rMembers.getConstArray(); + + for ( sal_Int32 nPos = rMembers.getLength(); nPos--; ) + { + if (rName == pMembers[nPos]->getName()) + { + aRet <<= Reference< XTypeDescription >( + pMembers[nPos], UNO_QUERY_THROW ); + break; + } + } + if (! aRet.hasValue()) + { + // member not found: + throw NoSuchElementException( + rName, static_cast< OWeakObject * >(this) ); + } + } + // test for instantiated polymorphic struct types: + else if (rName.indexOf('<') >= 0) + { + aRet <<= getInstantiatedStruct(rName); + } + else if (rName.indexOf( '.' ) < 0) // test for simple/ build in types + { + aRet = getSimpleType( rName ); + } + + if (! aRet.hasValue()) + { + // last, try callback chain + for ( ProviderVector::const_iterator iPos( _aProviders.begin() ); + iPos != _aProviders.end(); ++iPos ) + { + try + { + if ((aRet = (*iPos)->getByHierarchicalName( + rName )).hasValue()) + { + break; + } + } + catch (NoSuchElementException &) + { + } + } + } + + // update cache + if (_bCaching && aRet.hasValue()) + _aElements.setValue( rName, aRet ); + } + + if (! aRet.hasValue()) + { + throw NoSuchElementException( + rName, static_cast< OWeakObject * >(this) ); + } + return aRet; +} +//__________________________________________________________________________________________________ +sal_Bool ManagerImpl::hasByHierarchicalName( const OUString & rName ) + throw(::com::sun::star::uno::RuntimeException) +{ + try + { + return getByHierarchicalName( rName ).hasValue(); + } + catch (NoSuchElementException &) + { + } + return sal_False; +} +} + +namespace stoc_bootstrap +{ +//================================================================================================== +Reference< XInterface > SAL_CALL ManagerImpl_create( + Reference< XComponentContext > const & xContext ) + SAL_THROW( (::com::sun::star::uno::Exception) ) +{ + sal_Int32 nCacheSize = CACHE_SIZE; + if (xContext.is()) { + xContext->getValueByName( + OUString( + RTL_CONSTASCII_USTRINGPARAM( + "/implementations/" IMPLNAME "/CacheSize"))) >>= + nCacheSize; + } + + return Reference< XInterface >( *new stoc_tdmgr::ManagerImpl( xContext, nCacheSize ) ); +} + +} + diff --git a/stoc/source/tdmanager/tdmgr_check.cxx b/stoc/source/tdmanager/tdmgr_check.cxx new file mode 100644 index 000000000000..0a19403532bf --- /dev/null +++ b/stoc/source/tdmanager/tdmgr_check.cxx @@ -0,0 +1,556 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include "tdmgr_common.hxx" +#include "rtl/ustrbuf.hxx" +#include "typelib/typedescription.h" +#include "com/sun/star/beans/PropertyAttribute.hpp" +#include "com/sun/star/reflection/XConstantsTypeDescription.hpp" +#include "com/sun/star/reflection/XIndirectTypeDescription.hpp" +#include "com/sun/star/reflection/XEnumTypeDescription.hpp" +#include "com/sun/star/reflection/XStructTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceTypeDescription2.hpp" +#include "com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp" +#include "com/sun/star/reflection/XServiceTypeDescription2.hpp" +#include "com/sun/star/reflection/XSingletonTypeDescription2.hpp" + + +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::stoc_tdmgr; + +namespace { + +OUString getTypeClassName( TypeClass tc ) +{ + typelib_EnumTypeDescription * typeDescr = 0; + OUString name = OUSTR("com.sun.star.uno.TypeClass"); + typelib_typedescription_getByName( + reinterpret_cast<typelib_TypeDescription **>(&typeDescr), name.pData ); + OSL_ASSERT( typeDescr != 0 ); + if (typeDescr == 0) + return OUSTR("Cannot get type description of ") + name; + typelib_typedescription_complete( + reinterpret_cast<typelib_TypeDescription **>(&typeDescr) ); + + sal_Int32 const * pValues = typeDescr->pEnumValues; + sal_Int32 nPos = typeDescr->nEnumValues; + while (nPos--) + { + if (pValues[ nPos ] == (sal_Int32) tc) + break; + } + if (nPos >= 0) + name = typeDescr->ppEnumNames[ nPos ]; + else + name = OUSTR("unknown TypeClass value: ") + + OUString::valueOf( (sal_Int32) tc ); + + typelib_typedescription_release( + reinterpret_cast<typelib_TypeDescription *>(typeDescr) ); + return name; +} + +OUString getPropertyFlagsAsString( sal_Int16 attributes ) +{ + OUStringBuffer buf; + if ((attributes & beans::PropertyAttribute::MAYBEVOID) != 0) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("MAYBEVOID, ") ); + if ((attributes & beans::PropertyAttribute::BOUND) != 0) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("BOUND, ") ); + if ((attributes & beans::PropertyAttribute::CONSTRAINED) != 0) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("CONSTRAINED, ") ); + if ((attributes & beans::PropertyAttribute::TRANSIENT) != 0) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("TRANSIENT, ") ); + if ((attributes & beans::PropertyAttribute::READONLY) != 0) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("READONLY, ") ); + if ((attributes & beans::PropertyAttribute::MAYBEAMBIGUOUS) != 0) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("MAYBEAMBIGUOUS, ") ); + if ((attributes & beans::PropertyAttribute::MAYBEDEFAULT) != 0) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("MAYBEDEFAULT, ") ); + if ((attributes & beans::PropertyAttribute::REMOVEABLE) != 0) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("REMOVEABLE, ") ); + if ((attributes & beans::PropertyAttribute::OPTIONAL) != 0) + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("OPTIONAL") ); + else if (buf.getLength() > 0) + buf.setLength( buf.getLength() - 2 ); // truncate ", " + return buf.makeStringAndClear(); +} + +void typeError( OUString const & msg, OUString const & context ) +{ + OUStringBuffer buf; + if (context.getLength() > 0) { + buf.append( static_cast<sal_Unicode>('[') ); + buf.append( context ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] ") ); + } + buf.append( msg ); + throw IncompatibleTypeException( buf.makeStringAndClear() ); +} + +template<typename T> +void checkSeq( Sequence< Reference<T> > const & newTypes, + Sequence< Reference<T> > const & existingTypes, + OUString const & context, + bool optionalMode = false ) +{ + sal_Int32 len = newTypes.getLength(); + if (len != existingTypes.getLength()) + { + if (!optionalMode || len < newTypes.getLength()) + typeError( OUSTR("Different number of types!"), context ); + len = existingTypes.getLength(); + } + + Reference<T> const * pNewTypes = newTypes.getConstArray(); + Reference<T> const * pExistingTypes = existingTypes.getConstArray(); + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + OUStringBuffer buf; + buf.append( context ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", position ") ); + buf.append( pos ); + check( pNewTypes[pos].get(), pExistingTypes[pos].get(), + buf.makeStringAndClear() ); + } +} + +void checkEnum( + Reference<reflection::XEnumTypeDescription> const & xNewTD, + Reference<reflection::XEnumTypeDescription> const & xExistingTD ) +{ + if (xNewTD->getEnumNames() != xExistingTD->getEnumNames()) + typeError( OUSTR("ENUM names don't match!"), xNewTD->getName() ); + if (xNewTD->getEnumValues() != xExistingTD->getEnumValues()) + typeError( OUSTR("ENUM values don't match!"), xNewTD->getName() ); +} + +void checkStruct( + Reference<reflection::XCompoundTypeDescription> const & xNewTD, + Reference<reflection::XCompoundTypeDescription> const & xExistingTD ) +{ + check( xNewTD->getBaseType(), xExistingTD->getBaseType(), + xNewTD->getName() + OUSTR(", base type") ); + checkSeq( xNewTD->getMemberTypes(), xExistingTD->getMemberTypes(), + xNewTD->getName() + OUSTR(", member types") ); + + if (xNewTD->getMemberNames() != xExistingTD->getMemberNames()) + typeError( OUSTR("Different member names!"), xNewTD->getName() ); + + if (xNewTD->getTypeClass() == TypeClass_STRUCT) + { + Reference<reflection::XStructTypeDescription> xNewStructTD( + xNewTD, UNO_QUERY ); + Reference<reflection::XStructTypeDescription> xExistingStructTD( + xExistingTD, UNO_QUERY ); + if (xNewStructTD.is() && xExistingStructTD.is()) + { + if (xNewStructTD->getTypeParameters() != + xExistingStructTD->getTypeParameters()) + typeError( OUSTR("Different type parameters of instantiated " + "polymorphic STRUCT!"), xNewTD->getName() ); + checkSeq( xNewStructTD->getTypeArguments(), + xExistingStructTD->getTypeArguments(), + xNewTD->getName() + OUSTR(", argument types") ); + } + else if (xNewStructTD.is() || xExistingStructTD.is()) + typeError( OUSTR("Mixing polymorphic STRUCT types " + "with non-polymorphic!"), xNewTD->getName() ); + } +} + +void checkInterface( + Reference<reflection::XInterfaceTypeDescription2> const & xNewTD, + Reference<reflection::XInterfaceTypeDescription2> const & xExistingTD ) +{ + checkSeq( xNewTD->getBaseTypes(), xExistingTD->getBaseTypes(), + xNewTD->getName() + OUSTR(", base types") ); + checkSeq(xNewTD->getOptionalBaseTypes(),xExistingTD->getOptionalBaseTypes(), + xNewTD->getName() + OUSTR(", optional base types") ); + checkSeq( xNewTD->getMembers(), xExistingTD->getMembers(), + xNewTD->getName() + OUSTR(", members") ); +} + +void checkRestParam( Reference<reflection::XParameter> const & xNewParam, + Reference<reflection::XParameter> const & xExistingParam, + OUString const & context ) +{ + if (xNewParam->isRestParameter() != xExistingParam->isRestParameter()) + typeError( OUSTR("Different ... parameters specified!"), context ); +} + +void checkRestParam( Reference<reflection::XMethodParameter> const &, + Reference<reflection::XMethodParameter> const &, + OUString const & ) +{ +} + +template<typename T> +void checkParameters( Sequence< Reference<T> > const & newParams, + Sequence< Reference<T> > const & existingParams, + OUString const & context_ ) +{ + sal_Int32 len = newParams.getLength(); + if (len != existingParams.getLength()) + typeError( OUSTR("Different number of parameters!"), context_ ); + Reference<T> const * pNewParams = newParams.getConstArray(); + Reference<T> const * pExistingParams = existingParams.getConstArray(); + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + Reference<T> const & xNewParam = pNewParams[pos]; + Reference<T> const & xExistingParam = pExistingParams[pos]; + + OUStringBuffer buf; + buf.append( context_ ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", parameter ") ); + buf.append( pos ); + OSL_ASSERT( pos == xNewParam->getPosition() && + pos == xExistingParam->getPosition() ); + OUString context( buf.makeStringAndClear() ); + + if (xNewParam->getName() != xExistingParam->getName()) + { + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("Name differs: ") ); + buf.append( xNewParam->getName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") ); + buf.append( xExistingParam->getName() ); + typeError( buf.makeStringAndClear(), context ); + } + check( xNewParam->getType(), xExistingParam->getType(), context ); + + if (xNewParam->isIn() != xExistingParam->isIn()) + typeError( OUSTR("IN attribute differs!"), context ); + if (xNewParam->isOut() != xExistingParam->isOut()) + typeError( OUSTR("OUT attribute differs!"), context ); + checkRestParam( xNewParam, xExistingParam, context ); + } +} + +static void checkMethod( + Reference<reflection::XInterfaceMethodTypeDescription> const & xNewTD, + Reference<reflection::XInterfaceMethodTypeDescription> const & xExistingTD ) +{ + check( xNewTD->getReturnType(), xExistingTD->getReturnType(), + xNewTD->getName() ); + + if (xNewTD->isOneway() != xExistingTD->isOneway()) + typeError( OUSTR("Methods have differing OneWay attribute!"), + xNewTD->getName() ); + + checkParameters( xNewTD->getParameters(), xExistingTD->getParameters(), + xNewTD->getName() ); + + checkSeq( xNewTD->getExceptions(), xExistingTD->getExceptions(), + xNewTD->getName() + OUSTR(", declared exceptions") ); +} + +void checkAttribute( + Reference<reflection::XInterfaceAttributeTypeDescription2> const & xNewTD, + Reference<reflection::XInterfaceAttributeTypeDescription2> + const & xExistingTD ) +{ + if (xNewTD->isReadOnly() != xExistingTD->isReadOnly()) + typeError( OUSTR("ReadOnly attribute differs!"), xNewTD->getName() ); + + check( xNewTD->getType(), xExistingTD->getType(), + xNewTD->getName() + OUSTR(", attribute type") ); + + if (xNewTD->isBound() != xExistingTD->isBound()) + typeError( OUSTR("Bound attribute differs!"), xNewTD->getName() ); + + checkSeq( xNewTD->getGetExceptions(), xExistingTD->getGetExceptions(), + xNewTD->getName() + OUSTR(", getter exceptions") ); + checkSeq( xNewTD->getSetExceptions(), xExistingTD->getSetExceptions(), + xNewTD->getName() + OUSTR(", setter exceptions") ); +} + +void checkProperty( + Reference<reflection::XPropertyTypeDescription> const & xNewTD, + Reference<reflection::XPropertyTypeDescription> const & xExistingTD ) +{ + if (xNewTD->getPropertyFlags() != xExistingTD->getPropertyFlags()) + { + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "Different set of property flags: { ") ); + buf.append( getPropertyFlagsAsString( + xNewTD->getPropertyFlags() ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" } (new), { ") ); + buf.append( getPropertyFlagsAsString( + xExistingTD->getPropertyFlags() ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" } (existing)!") ); + typeError( buf.makeStringAndClear(), xNewTD->getName() ); + } + + check( xNewTD->getPropertyTypeDescription(), + xExistingTD->getPropertyTypeDescription(), + xNewTD->getName() ); +} + +void checkSingleton( + Reference<reflection::XSingletonTypeDescription2> const & xNewTD, + Reference<reflection::XSingletonTypeDescription2> const & xExistingTD ) +{ + sal_Bool ifaceBased = xNewTD->isInterfaceBased(); + if (ifaceBased != xExistingTD->isInterfaceBased()) + typeError( + OUSTR("Mixing interface and NON-interface based singletons!"), + xNewTD->getName() ); + if (ifaceBased) + check( xNewTD->getInterface(), xExistingTD->getInterface(), + xNewTD->getName() ); + else + check( xNewTD->getService().get(), xExistingTD->getService().get(), + xNewTD->getName() ); +} + +void checkService( + Reference<reflection::XServiceTypeDescription2> const & xNewTD, + Reference<reflection::XServiceTypeDescription2> const & xExistingTD ) +{ + sal_Bool singleIfaceBased = xNewTD->isSingleInterfaceBased(); + if (singleIfaceBased != xExistingTD->isSingleInterfaceBased()) + typeError( OUSTR("Mixing interface and NON-interface based services!"), + xNewTD->getName() ); + if (singleIfaceBased) + { + check( xNewTD->getInterface(), xExistingTD->getInterface(), + xNewTD->getName() ); + Sequence< Reference<reflection::XServiceConstructorDescription> > + newCtors( xNewTD->getConstructors() ); + Sequence< Reference<reflection::XServiceConstructorDescription> > + existingCtors( xExistingTD->getConstructors() ); + sal_Int32 len = newCtors.getLength(); + if (len != existingCtors.getLength()) + typeError( OUSTR("Different number of service constructors!"), + xNewTD->getName() ); + Reference<reflection::XServiceConstructorDescription> const * + pNewCtors = newCtors.getConstArray(); + Reference<reflection::XServiceConstructorDescription> const * + pExistingCtors = existingCtors.getConstArray(); + for ( sal_Int32 pos = 0; pos < len; ++pos ) + { + Reference<reflection::XServiceConstructorDescription> const & + xNewCtor = pNewCtors[pos]; + Reference<reflection::XServiceConstructorDescription> const & + xExistingCtor = pExistingCtors[pos]; + + if (xNewCtor->getName() != xExistingCtor->getName()) + { + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + "Different constructor names: ") ); + buf.append( xNewCtor->getName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (new), ") ); + buf.append( xExistingCtor->getName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (existing)!") ); + typeError( buf.makeStringAndClear(), xNewTD->getName() ); + } + + OUStringBuffer buf; + buf.append( xNewTD->getName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", constructor ") ); + buf.append( xNewCtor->getName() ); + OUString context( buf.makeStringAndClear() ); + checkParameters( xNewCtor->getParameters(), + xExistingCtor->getParameters(), + context ); + checkSeq( xNewCtor->getExceptions(), xExistingCtor->getExceptions(), + context + OUSTR(", exceptions") ); + } + } + else // old-style service descriptions: + { + checkSeq( xNewTD->getMandatoryServices(), + xExistingTD->getMandatoryServices(), + xNewTD->getName() + OUSTR(", mandatory services") ); + checkSeq( xNewTD->getOptionalServices(), + xExistingTD->getOptionalServices(), + xNewTD->getName() + OUSTR(", optional services"), + true /* optionalMode */ ); + checkSeq( xNewTD->getMandatoryInterfaces(), + xExistingTD->getMandatoryInterfaces(), + xNewTD->getName() + OUSTR(", mandatory interfaces") ); + checkSeq( xNewTD->getOptionalInterfaces(), + xExistingTD->getOptionalInterfaces(), + xNewTD->getName() + OUSTR(", optional interfaces"), + true /* optionalMode */ ); + + Sequence< Reference<reflection::XPropertyTypeDescription> > + newProperties( xNewTD->getProperties() ); + Sequence< Reference<reflection::XPropertyTypeDescription> > + existingProperties( xExistingTD->getProperties() ); + checkSeq( newProperties, existingProperties, + xNewTD->getName() + OUSTR(", properties"), + true /* optionalMode */ ); + if (newProperties.getLength() > existingProperties.getLength()) + { + // check whether all added properties are OPTIONAL: + Reference<reflection::XPropertyTypeDescription> const * + pNewProperties = newProperties.getConstArray(); + for ( sal_Int32 pos = existingProperties.getLength() + 1; + pos < newProperties.getLength(); ++pos ) + { + if ((pNewProperties[pos]->getPropertyFlags() & + beans::PropertyAttribute::OPTIONAL) == 0) + typeError( OUSTR("New property is not OPTIONAL!"), + pNewProperties[pos]->getName() ); + } + } + } +} + +} + +namespace stoc_tdmgr { + +void check( Reference<reflection::XTypeDescription> const & xNewTD, + Reference<reflection::XTypeDescription> const & xExistingTD, + OUString const & context ) +{ + if (xNewTD == xExistingTD) + return; + if (xNewTD->getName() != xExistingTD->getName()) + { + OUStringBuffer buf; + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("Different type names: ") ); + buf.append( xNewTD->getName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (new), ") ); + buf.append( xExistingTD->getName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (existing)!") ); + typeError( buf.makeStringAndClear(), context ); + } + + TypeClass tc = xNewTD->getTypeClass(); + if (tc != xExistingTD->getTypeClass()) + { + OUStringBuffer buf; + buf.append( xNewTD->getName() ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( + " has different type classes: ") ); + buf.append( getTypeClassName( tc ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (new), ") ); + buf.append( getTypeClassName( xExistingTD->getTypeClass() ) ); + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (existing)!") ); + typeError( buf.makeStringAndClear(), context ); + } + + switch (tc) + { + case TypeClass_ENUM: + checkEnum( Reference<reflection::XEnumTypeDescription>( + xNewTD, UNO_QUERY_THROW ), + Reference<reflection::XEnumTypeDescription>( + xExistingTD, UNO_QUERY_THROW ) ); + break; + + case TypeClass_TYPEDEF: + case TypeClass_SEQUENCE: + check( Reference<reflection::XIndirectTypeDescription>( + xNewTD, UNO_QUERY_THROW )->getReferencedType(), + Reference<reflection::XIndirectTypeDescription>( + xExistingTD, UNO_QUERY_THROW )->getReferencedType() ); + break; + + case TypeClass_STRUCT: + case TypeClass_EXCEPTION: + checkStruct( Reference<reflection::XCompoundTypeDescription>( + xNewTD, UNO_QUERY_THROW ), + Reference<reflection::XCompoundTypeDescription>( + xExistingTD, UNO_QUERY_THROW ) ); + break; + + case TypeClass_INTERFACE: + checkInterface( Reference<reflection::XInterfaceTypeDescription2>( + xNewTD, UNO_QUERY_THROW ), + Reference<reflection::XInterfaceTypeDescription2>( + xExistingTD, UNO_QUERY_THROW ) ); + break; + + case TypeClass_SERVICE: + checkService( Reference<reflection::XServiceTypeDescription2>( + xNewTD, UNO_QUERY_THROW ), + Reference<reflection::XServiceTypeDescription2>( + xExistingTD, UNO_QUERY_THROW ) ); + break; + + case TypeClass_INTERFACE_METHOD: + checkMethod( Reference<reflection::XInterfaceMethodTypeDescription>( + xNewTD, UNO_QUERY_THROW ), + Reference<reflection::XInterfaceMethodTypeDescription>( + xExistingTD, UNO_QUERY_THROW ) ); + break; + case TypeClass_INTERFACE_ATTRIBUTE: + checkAttribute( + Reference<reflection::XInterfaceAttributeTypeDescription2>( + xNewTD, UNO_QUERY_THROW ), + Reference<reflection::XInterfaceAttributeTypeDescription2>( + xExistingTD, UNO_QUERY_THROW ) ); + break; + + case TypeClass_PROPERTY: + checkProperty( Reference<reflection::XPropertyTypeDescription>( + xNewTD, UNO_QUERY_THROW ), + Reference<reflection::XPropertyTypeDescription>( + xExistingTD, UNO_QUERY_THROW ) ); + break; + + case TypeClass_CONSTANT: + if (Reference<reflection::XConstantTypeDescription>( + xNewTD, UNO_QUERY_THROW )->getConstantValue() != + Reference<reflection::XConstantTypeDescription>( + xExistingTD, UNO_QUERY_THROW )->getConstantValue()) + typeError( OUSTR("Different constant value!"), xNewTD->getName() ); + break; + case TypeClass_CONSTANTS: + checkSeq( Reference<reflection::XConstantsTypeDescription>( + xNewTD, UNO_QUERY_THROW )->getConstants(), + Reference<reflection::XConstantsTypeDescription>( + xExistingTD, UNO_QUERY_THROW )->getConstants(), + xNewTD->getName() ); + break; + + case TypeClass_SINGLETON: + checkSingleton( Reference<reflection::XSingletonTypeDescription2>( + xNewTD, UNO_QUERY_THROW ), + Reference<reflection::XSingletonTypeDescription2>( + xExistingTD, UNO_QUERY_THROW ) ); + break; + + default: + break; + } +} + +} diff --git a/stoc/source/tdmanager/tdmgr_common.hxx b/stoc/source/tdmanager/tdmgr_common.hxx new file mode 100644 index 000000000000..5d640e99f919 --- /dev/null +++ b/stoc/source/tdmanager/tdmgr_common.hxx @@ -0,0 +1,60 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _STOC_TDMGR_COMMON_HXX +#define _STOC_TDMGR_COMMON_HXX + +#include <rtl/unload.h> + +#include "com/sun/star/reflection/XTypeDescription.hpp" + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) +#define ARLEN(x) (sizeof (x) / sizeof *(x)) + + +namespace css = ::com::sun::star; + +namespace stoc_tdmgr +{ + extern rtl_StandardModuleCount g_moduleCount; + +struct IncompatibleTypeException +{ + ::rtl::OUString m_cause; + IncompatibleTypeException( ::rtl::OUString const & cause ) + : m_cause( cause ) {} +}; + +void check( + css::uno::Reference<css::reflection::XTypeDescription> const & xNewTD, + css::uno::Reference<css::reflection::XTypeDescription> const & xExistingTD, + ::rtl::OUString const & context = ::rtl::OUString() ); +/* throw (css::uno::RuntimeException, IncompatibleTypeException) */ + +} // namespace stoc_tdmgr + +#endif /* _STOC_TDMGR_COMMON_HXX */ diff --git a/stoc/source/tdmanager/tdmgr_tdenumeration.cxx b/stoc/source/tdmanager/tdmgr_tdenumeration.cxx new file mode 100644 index 000000000000..c1815c932db5 --- /dev/null +++ b/stoc/source/tdmanager/tdmgr_tdenumeration.cxx @@ -0,0 +1,187 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include <osl/diagnose.h> +#include "tdmgr_common.hxx" +#include "tdmgr_tdenumeration.hxx" + +using namespace com::sun::star; + +extern rtl_StandardModuleCount g_moduleCount; + +namespace stoc_tdmgr +{ + +//========================================================================= +//========================================================================= +// +// TypeDescriptionEnumerationImpl Implementation. +// +//========================================================================= +//========================================================================= + +TypeDescriptionEnumerationImpl::TypeDescriptionEnumerationImpl( + const rtl::OUString & rModuleName, + const com::sun::star::uno::Sequence< + com::sun::star::uno::TypeClass > & rTypes, + com::sun::star::reflection::TypeDescriptionSearchDepth eDepth, + const TDEnumerationAccessStack & rTDEAS ) +: m_aModuleName( rModuleName ), + m_aTypes( rTypes ), + m_eDepth( eDepth ), + m_aChildren( rTDEAS ) +{ + ::g_moduleCount.modCnt.acquire( &::g_moduleCount.modCnt ); +} + +//========================================================================= +// virtual +TypeDescriptionEnumerationImpl::~TypeDescriptionEnumerationImpl() +{ + ::g_moduleCount.modCnt.release( &::g_moduleCount.modCnt ); +} + +//========================================================================= +// +// XEnumeration (base of XTypeDescriptionEnumeration) methods +// +//========================================================================= + +// virtual +sal_Bool SAL_CALL TypeDescriptionEnumerationImpl::hasMoreElements() + throw ( uno::RuntimeException ) +{ + uno::Reference< reflection::XTypeDescriptionEnumeration > xEnum + = queryCurrentChildEnumeration(); + if ( xEnum.is() ) + return xEnum->hasMoreElements(); + + return sal_False; +} + +//========================================================================= +// virtual +uno::Any SAL_CALL TypeDescriptionEnumerationImpl::nextElement() + throw ( container::NoSuchElementException, + lang::WrappedTargetException, + uno::RuntimeException ) +{ + uno::Reference< reflection::XTypeDescriptionEnumeration > xEnum + = queryCurrentChildEnumeration(); + if ( xEnum.is() ) + return xEnum->nextElement(); + + throw container::NoSuchElementException( + rtl::OUString::createFromAscii( + "No further elements in enumeration!" ), + static_cast< cppu::OWeakObject * >( this ) ); +} + +//========================================================================= +// +// XTypeDescriptionEnumeration methods +// +//========================================================================= + +// virtual +uno::Reference< reflection::XTypeDescription > SAL_CALL +TypeDescriptionEnumerationImpl::nextTypeDescription() + throw ( container::NoSuchElementException, + uno::RuntimeException ) +{ + uno::Reference< reflection::XTypeDescriptionEnumeration > xEnum + = queryCurrentChildEnumeration(); + if ( xEnum.is() ) + return xEnum->nextTypeDescription(); + + throw container::NoSuchElementException( + rtl::OUString::createFromAscii( + "No further elements in enumeration!" ), + static_cast< cppu::OWeakObject * >( this ) ); +} + +//========================================================================= +uno::Reference< reflection::XTypeDescriptionEnumeration > +TypeDescriptionEnumerationImpl::queryCurrentChildEnumeration() +{ + osl::MutexGuard aGuard( m_aMutex ); + + for (;;) + { + if ( m_xEnum.is() ) + { + if ( m_xEnum->hasMoreElements() ) + { + return m_xEnum; + } + else + { + // Forget about enumeration without further elements. Try next. + m_xEnum.clear(); + } + } + + // Note: m_xEnum is always null here. + + if ( m_aChildren.empty() ) + { + // No child enumerations left. + return m_xEnum; + } + + try + { + m_xEnum = + m_aChildren.top()->createTypeDescriptionEnumeration( + m_aModuleName, m_aTypes, m_eDepth ); + } + catch ( reflection::NoSuchTypeNameException const & ) + { + OSL_ENSURE( sal_False, + "TypeDescriptionEnumerationImpl::queryCurrentChildEnumeration " + "- Caught NoSuchTypeNameException!" ); + } + catch ( reflection::InvalidTypeNameException const & ) + { + OSL_ENSURE( sal_False, + "TypeDescriptionEnumerationImpl::queryCurrentChildEnumeration " + "- Caught InvalidTypeNameException!" ); + } + + // We're done with this enumeration access in any case (Either + // enumeration was successfully created or creation failed for some + // reason). + m_aChildren.pop(); + } + + // unreachable +} + +} // namespace stoc_tdmgr + diff --git a/stoc/source/tdmanager/tdmgr_tdenumeration.hxx b/stoc/source/tdmanager/tdmgr_tdenumeration.hxx new file mode 100644 index 000000000000..1b383af538c1 --- /dev/null +++ b/stoc/source/tdmanager/tdmgr_tdenumeration.hxx @@ -0,0 +1,89 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _STOC_TDMGR_TDENUMERATION_HXX +#define _STOC_TDMGR_TDENUMERATION_HXX + +#include <stack> +#include <osl/mutex.hxx> +#include <com/sun/star/reflection/XTypeDescriptionEnumeration.hpp> +#include <com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp> +#include <cppuhelper/implbase1.hxx> + +namespace stoc_tdmgr +{ + +typedef std::stack< com::sun::star::uno::Reference< + com::sun::star::reflection::XTypeDescriptionEnumerationAccess > > + TDEnumerationAccessStack; + +class TypeDescriptionEnumerationImpl + : public cppu::WeakImplHelper1< + com::sun::star::reflection::XTypeDescriptionEnumeration > +{ +public: + TypeDescriptionEnumerationImpl( + const rtl::OUString & rModuleName, + const com::sun::star::uno::Sequence< + com::sun::star::uno::TypeClass > & rTypes, + com::sun::star::reflection::TypeDescriptionSearchDepth eDepth, + const TDEnumerationAccessStack & rTDEAS ); + virtual ~TypeDescriptionEnumerationImpl(); + + // XEnumeration (base of XTypeDescriptionEnumeration) + virtual sal_Bool SAL_CALL hasMoreElements() + throw ( ::com::sun::star::uno::RuntimeException ); + virtual ::com::sun::star::uno::Any SAL_CALL nextElement() + throw ( ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException ); + + // XTypeDescriptionEnumeration + virtual ::com::sun::star::uno::Reference< + ::com::sun::star::reflection::XTypeDescription > SAL_CALL + nextTypeDescription() + throw ( ::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException ); + +private: + com::sun::star::uno::Reference< + com::sun::star::reflection::XTypeDescriptionEnumeration > + queryCurrentChildEnumeration(); + + osl::Mutex m_aMutex; + rtl::OUString m_aModuleName; + com::sun::star::uno::Sequence< com::sun::star::uno::TypeClass > m_aTypes; + com::sun::star::reflection::TypeDescriptionSearchDepth m_eDepth; + TDEnumerationAccessStack m_aChildren; + com::sun::star::uno::Reference< + com::sun::star::reflection::XTypeDescriptionEnumeration > m_xEnum; +}; + +} // namespace stoc_tdmgr + +#endif /* _STOC_TDMGR_TDENUMERATION_HXX */ + diff --git a/stoc/source/typeconv/convert.cxx b/stoc/source/typeconv/convert.cxx new file mode 100644 index 000000000000..0b81d3e49d1c --- /dev/null +++ b/stoc/source/typeconv/convert.cxx @@ -0,0 +1,963 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include <osl/diagnose.h> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/implementationentry.hxx> +#include <cppuhelper/implbase2.hxx> + +#include <typelib/typedescription.hxx> +#include <uno/data.h> + +#ifdef WNT +#include <cmath> +#else +#include <math.h> +#endif +#include <float.h> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/script/XTypeConverter.hpp> +#include <com/sun/star/script/FailReason.hpp> +#include <com/sun/star/container/XSet.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> + +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::script; +using namespace com::sun::star::registry; +using namespace cppu; +using namespace rtl; +using namespace osl; + +#define SERVICENAME "com.sun.star.script.Converter" +#define IMPLNAME "com.sun.star.comp.stoc.TypeConverter" + + +extern rtl_StandardModuleCount g_moduleCount; + +namespace stoc_services +{ +Sequence< OUString > tcv_getSupportedServiceNames() +{ + static Sequence < OUString > *pNames = 0; + if( ! pNames ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( !pNames ) + { + static Sequence< OUString > seqNames(1); + seqNames.getArray()[0] = OUString(RTL_CONSTASCII_USTRINGPARAM(SERVICENAME)); + pNames = &seqNames; + } + } + return *pNames; +} + +OUString tcv_getImplementationName() +{ + static OUString *pImplName = 0; + if( ! pImplName ) + { + MutexGuard guard( Mutex::getGlobalMutex() ); + if( ! pImplName ) + { + static OUString implName( RTL_CONSTASCII_USTRINGPARAM( IMPLNAME ) ); + pImplName = &implName; + } + } + return *pImplName; +} +} + +namespace stoc_tcv +{ + +static const sal_uInt64 SAL_UINT64_MAX = + ((((sal_uInt64)0xffffffff) << 32) | (sal_uInt64)0xffffffff); +static const sal_Int64 SAL_INT64_MAX = + (sal_Int64)((((sal_uInt64)0x7fffffff) << 32) | (sal_uInt64)0xffffffff); +static const sal_Int64 SAL_INT64_MIN = + (sal_Int64)(((sal_uInt64)0x80000000) << 32); + +/* MS Visual C++ no conversion from unsigned __int64 to double */ +#ifdef _MSC_VER +static const double DOUBLE_SAL_UINT64_MAX = ((((double)SAL_INT64_MAX) * 2) + 1); + +static inline double unsigned_int64_to_double( sal_uInt64 n ) SAL_THROW( () ) +{ + sal_uInt64 n2 = (n / 3); + n -= (2 * n2); + return (((double)(sal_Int64)n2) * 2.0) + ((double)(sal_Int64)n); +} +#else +static const double DOUBLE_SAL_UINT64_MAX = + (double)((((sal_uInt64)0xffffffff) << 32) | (sal_uInt64)0xffffffff); + +static inline double unsigned_int64_to_double( sal_uInt64 n ) SAL_THROW( () ) +{ + return (double)n; +} +#endif + + +//-------------------------------------------------------------------------------------------------- +static inline double round( double aVal ) +{ + sal_Bool bPos = (aVal >= 0.0); // + aVal = ::fabs( aVal ); + double aUpper = ::ceil( aVal ); + + aVal = ((aUpper-aVal) <= 0.5) ? aUpper : (aUpper - 1.0); + return (bPos ? aVal : -aVal); +} + +//-------------------------------------------------------------------------------------------------- +static sal_Bool getNumericValue( double & rfVal, const OUString & rStr ) +{ + double fRet = rStr.toDouble(); + if (fRet == 0.0) + { + sal_Int32 nLen = rStr.getLength(); + if (!nLen || (nLen == 1 && rStr[0] == '0')) // common case + { + rfVal = 0.0; + return sal_True; + } + + OUString trim( rStr.trim() ); + + // try hex + sal_Int32 nX = trim.indexOf( 'x' ); + if (nX < 0) + nX = trim.indexOf( 'X' ); + + if (nX > 0 && trim[nX-1] == '0') // 0x + { + sal_Bool bNeg = sal_False; + switch (nX) + { + case 2: // (+|-)0x... + if (trim[0] == '-') + bNeg = sal_True; + else if (trim[0] != '+') + return sal_False; + case 1: // 0x... + break; + default: + return sal_False; + } + + OUString aHexRest( trim.copy( nX+1 ) ); + sal_Int64 nRet = aHexRest.toInt64( 16 ); + + if (nRet == 0) + { + for ( sal_Int32 nPos = aHexRest.getLength(); nPos--; ) + { + if (aHexRest[nPos] != '0') + return sal_False; + } + } + + rfVal = (bNeg ? -(double)nRet : (double)nRet); + return sal_True; + } + + nLen = trim.getLength(); + sal_Int32 nPos = 0; + + // skip +/- + if (nLen && (trim[0] == '-' || trim[0] == '+')) + ++nPos; + + while (nPos < nLen) // skip leading zeros + { + if (trim[nPos] != '0') + { + if (trim[nPos] != '.') + return sal_False; + ++nPos; + while (nPos < nLen) // skip trailing zeros + { + if (trim[nPos] != '0') + return sal_False; + ++nPos; + } + break; + } + ++nPos; + } + } + rfVal = fRet; + return sal_True; +} + +//================================================================================================== +static sal_Bool getHyperValue( sal_Int64 & rnVal, const OUString & rStr ) +{ + sal_Int32 nLen = rStr.getLength(); + if (!nLen || (nLen == 1 && rStr[0] == '0')) // common case + { + rnVal = 0; + return sal_True; + } + + OUString trim( rStr.trim() ); + + // try hex + sal_Int32 nX = trim.indexOf( 'x' ); + if (nX < 0) + nX = trim.indexOf( 'X' ); + + if (nX >= 0) + { + if (nX > 0 && trim[nX-1] == '0') // 0x + { + sal_Bool bNeg = sal_False; + switch (nX) + { + case 2: // (+|-)0x... + if (trim[0] == '-') + bNeg = sal_True; + else if (trim[0] != '+') + return sal_False; + case 1: // 0x... + break; + default: + return sal_False; + } + + OUString aHexRest( trim.copy( nX+1 ) ); + sal_Int64 nRet = aHexRest.toInt64( 16 ); + + if (nRet == 0) + { + for ( sal_Int32 nPos = aHexRest.getLength(); nPos--; ) + { + if (aHexRest[nPos] != '0') + return sal_False; + } + } + + rnVal = (bNeg ? -nRet : nRet); + return sal_True; + } + return sal_False; + } + + double fVal; + if (getNumericValue( fVal, rStr ) && + fVal >= (double)SAL_INT64_MIN && + fVal <= DOUBLE_SAL_UINT64_MAX) + { + rnVal = (sal_Int64)round( fVal ); + return sal_True; + } + return sal_False; +} + +//================================================================================================== +class TypeConverter_Impl : public WeakImplHelper2< XTypeConverter, XServiceInfo > +{ + // ...misc helpers... + sal_Int64 toHyper( + const Any& rAny, sal_Int64 min = SAL_INT64_MIN, sal_uInt64 max = SAL_UINT64_MAX ) + throw( CannotConvertException ); + double toDouble( const Any& rAny, double min = -DBL_MAX, double max = DBL_MAX ) const + throw( CannotConvertException ); + +public: + TypeConverter_Impl(); + virtual ~TypeConverter_Impl(); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() throw( RuntimeException ); + virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) + throw( RuntimeException ); + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(void) + throw( RuntimeException ); + + // XTypeConverter + virtual Any SAL_CALL convertTo( const Any& aFrom, const Type& DestinationType ) + throw( IllegalArgumentException, CannotConvertException, RuntimeException); + virtual Any SAL_CALL convertToSimpleType( const Any& aFrom, TypeClass aDestinationType ) + throw( IllegalArgumentException, CannotConvertException, RuntimeException); +}; + +TypeConverter_Impl::TypeConverter_Impl() +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); +} + +TypeConverter_Impl::~TypeConverter_Impl() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +// XServiceInfo +OUString TypeConverter_Impl::getImplementationName() throw( RuntimeException ) +{ + return stoc_services::tcv_getImplementationName(); +} + +// XServiceInfo +sal_Bool TypeConverter_Impl::supportsService(const OUString& ServiceName) throw( RuntimeException ) +{ + Sequence< OUString > aSNL = getSupportedServiceNames(); + const OUString * pArray = aSNL.getConstArray(); + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return sal_True; + return sal_False; +} + +// XServiceInfo +Sequence< OUString > TypeConverter_Impl::getSupportedServiceNames(void) throw( RuntimeException ) +{ + return stoc_services::tcv_getSupportedServiceNames(); +} + +//-------------------------------------------------------------------------------------------------- +sal_Int64 TypeConverter_Impl::toHyper( const Any& rAny, sal_Int64 min, sal_uInt64 max ) + throw( CannotConvertException ) +{ + sal_Int64 nRet; + TypeClass aDestinationClass = rAny.getValueTypeClass(); + + switch (aDestinationClass) + { + // ENUM + case TypeClass_ENUM: + nRet = *(sal_Int32 *)rAny.getValue(); + break; + // BOOL + case TypeClass_BOOLEAN: + nRet = (*(sal_Bool*)rAny.getValue() ? 1 : 0); + break; + // CHAR, BYTE + case TypeClass_CHAR: + nRet = *(sal_Unicode *)rAny.getValue(); + break; + case TypeClass_BYTE: + nRet = *(sal_Int8 *)rAny.getValue(); + break; + // SHORT + case TypeClass_SHORT: + nRet = *(sal_Int16 *)rAny.getValue(); + break; + // UNSIGNED SHORT + case TypeClass_UNSIGNED_SHORT: + nRet = *(sal_uInt16 *)rAny.getValue(); + break; + // LONG + case TypeClass_LONG: + nRet = *(sal_Int32 *)rAny.getValue(); + break; + // UNSIGNED LONG + case TypeClass_UNSIGNED_LONG: + nRet = *(sal_uInt32 *)rAny.getValue(); + break; + // HYPER + case TypeClass_HYPER: + nRet = *(sal_Int64 *)rAny.getValue(); + break; + // UNSIGNED HYPER + case TypeClass_UNSIGNED_HYPER: + { + nRet = *(sal_Int64 *)rAny.getValue(); + if ((min < 0 || (sal_uInt64)nRet >= (sal_uInt64)min) && // lower bound + (sal_uInt64)nRet <= max) // upper bound + { + return nRet; + } + throw CannotConvertException( + OUString( RTL_CONSTASCII_USTRINGPARAM("UNSIGNED HYPER out of range!") ), + Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 ); + } + + // FLOAT, DOUBLE + case TypeClass_FLOAT: + { + double fVal = round( *(float *)rAny.getValue() ); + nRet = (fVal > SAL_INT64_MAX ? (sal_Int64)(sal_uInt64)fVal : (sal_Int64)fVal); + if (fVal >= min && fVal <= unsigned_int64_to_double( max )) + { + return nRet; + } + throw CannotConvertException( + OUString( RTL_CONSTASCII_USTRINGPARAM("FLOAT out of range!") ), + Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 ); + } + case TypeClass_DOUBLE: + { + double fVal = round( *(double *)rAny.getValue() ); + nRet = (fVal > SAL_INT64_MAX ? (sal_Int64)(sal_uInt64)fVal : (sal_Int64)fVal); + if (fVal >= min && fVal <= unsigned_int64_to_double( max )) + { + return nRet; + } + throw CannotConvertException( + OUString( RTL_CONSTASCII_USTRINGPARAM("DOUBLE out of range!") ), + Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 ); + } + + // STRING + case TypeClass_STRING: + { + sal_Int64 fVal = SAL_CONST_INT64(0); + if (! getHyperValue( fVal, *(OUString const *)rAny.getValue() )) + { + throw CannotConvertException( + OUString( RTL_CONSTASCII_USTRINGPARAM("invalid STRING value!") ), + Reference<XInterface>(), aDestinationClass, FailReason::IS_NOT_NUMBER, 0 ); + } + nRet = (fVal > SAL_INT64_MAX ? (sal_Int64)(sal_uInt64)fVal : (sal_Int64)fVal); + if (fVal >= min && (fVal < 0 || ((sal_uInt64)fVal) <= max)) + return nRet; + throw CannotConvertException( + OUString( RTL_CONSTASCII_USTRINGPARAM("STRING value out of range!") ), + Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 ); + } + + default: + throw CannotConvertException( + OUString( RTL_CONSTASCII_USTRINGPARAM("TYPE is not supported!") ), + Reference<XInterface>(), aDestinationClass, FailReason::TYPE_NOT_SUPPORTED, 0 ); + } + + if (nRet >= min && (nRet < 0 || (sal_uInt64)nRet <= max)) + return nRet; + throw CannotConvertException( + OUString( RTL_CONSTASCII_USTRINGPARAM("VALUE is out of range!") ), + Reference<XInterface>(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 ); +} + +//-------------------------------------------------------------------------------------------------- +double TypeConverter_Impl::toDouble( const Any& rAny, double min, double max ) const + throw( CannotConvertException ) +{ + double fRet; + TypeClass aDestinationClass = rAny.getValueTypeClass(); + + switch (aDestinationClass) + { + // ENUM + case TypeClass_ENUM: + fRet = *(sal_Int32 *)rAny.getValue(); + break; + // BOOL + case TypeClass_BOOLEAN: + fRet = (*(sal_Bool*)rAny.getValue() ? 1.0 : 0.0); + break; + // CHAR, BYTE + case TypeClass_CHAR: + fRet = *(sal_Unicode *)rAny.getValue(); + break; + case TypeClass_BYTE: + fRet = *(sal_Int8 *)rAny.getValue(); + break; + // SHORT + case TypeClass_SHORT: + fRet = *(sal_Int16 *)rAny.getValue(); + break; + // UNSIGNED SHORT + case TypeClass_UNSIGNED_SHORT: + fRet = *(sal_uInt16 *)rAny.getValue(); + break; + // LONG + case TypeClass_LONG: + fRet = *(sal_Int32 *)rAny.getValue(); + break; + // UNSIGNED LONG + case TypeClass_UNSIGNED_LONG: + fRet = *(sal_uInt32 *)rAny.getValue(); + break; + // HYPER + case TypeClass_HYPER: + fRet = (double)*(sal_Int64 *)rAny.getValue(); + break; + // UNSIGNED HYPER + case TypeClass_UNSIGNED_HYPER: + fRet = unsigned_int64_to_double( *(sal_uInt64 const *)rAny.getValue() ); + break; + // FLOAT, DOUBLE + case TypeClass_FLOAT: + fRet = *(float *)rAny.getValue(); + break; + case TypeClass_DOUBLE: + fRet = *(double *)rAny.getValue(); + break; + + // STRING + case TypeClass_STRING: + { + if (! getNumericValue( fRet, *(OUString *)rAny.getValue() )) + { + throw CannotConvertException( + OUString( RTL_CONSTASCII_USTRINGPARAM("invalid STRING value!") ), + Reference<XInterface>(), aDestinationClass, FailReason::IS_NOT_NUMBER, 0 ); + } + break; + } + + default: + throw CannotConvertException( + OUString( RTL_CONSTASCII_USTRINGPARAM("TYPE is not supported!") ), + Reference< XInterface >(), aDestinationClass, FailReason::TYPE_NOT_SUPPORTED, 0 ); + } + + if (fRet >= min && fRet <= max) + return fRet; + throw CannotConvertException( + OUString( RTL_CONSTASCII_USTRINGPARAM("VALUE is out of range!") ), + Reference< XInterface >(), aDestinationClass, FailReason::OUT_OF_RANGE, 0 ); +} + +//-------------------------------------------------------------------------------------------------- +Any SAL_CALL TypeConverter_Impl::convertTo( const Any& rVal, const Type& aDestType ) + throw( IllegalArgumentException, CannotConvertException, RuntimeException) +{ + Type aSourceType = rVal.getValueType(); + if (aSourceType == aDestType) + return rVal; + + TypeClass aSourceClass = aSourceType.getTypeClass(); + TypeClass aDestinationClass = aDestType.getTypeClass(); + + Any aRet; + + // convert to... + switch (aDestinationClass) + { + // --- to VOID ------------------------------------------------------------------------------ + case TypeClass_VOID: + return Any(); + // --- to ANY ------------------------------------------------------------------------------- + case TypeClass_ANY: + return rVal; + + // --- to STRUCT, UNION, EXCEPTION ---------------------------------------------------------- + case TypeClass_STRUCT: +// case TypeClass_UNION: // xxx todo + case TypeClass_EXCEPTION: + { + // same types or destination type is derived source type? + TypeDescription aSourceTD( aSourceType ); + TypeDescription aDestTD( aDestType ); + if (typelib_typedescription_isAssignableFrom( aDestTD.get(), aSourceTD.get() )) + { + aRet.setValue( rVal.getValue(), aDestTD.get() ); // evtl. .uP.cAsT. + } + else + { + throw CannotConvertException( + OUString( RTL_CONSTASCII_USTRINGPARAM("value is not of same or derived type!") ), + Reference< XInterface >(), aDestinationClass, + FailReason::SOURCE_IS_NO_DERIVED_TYPE, 0 ); + } + break; + } + // --- to INTERFACE ------------------------------------------------------------------------- + case TypeClass_INTERFACE: + { + if (! rVal.hasValue()) + { + // void -> interface (null) + void * null_ref = 0; + aRet.setValue( &null_ref, aDestType ); + break; + } + + if (rVal.getValueTypeClass() != TypeClass_INTERFACE || + !*(XInterface * const *)rVal.getValue()) + { + throw CannotConvertException( + OUString( RTL_CONSTASCII_USTRINGPARAM("value is no interface!") ), + Reference< XInterface >(), aDestinationClass, FailReason::NO_SUCH_INTERFACE, 0 ); + } + if (! (aRet = (*(XInterface * const *)rVal.getValue())->queryInterface( + aDestType )).hasValue()) + { + throw CannotConvertException( + OUString( RTL_CONSTASCII_USTRINGPARAM("value has no such interface!") ), + Reference< XInterface >(), aDestinationClass, FailReason::NO_SUCH_INTERFACE, 0 ); + } + break; + } + // --- to SEQUENCE -------------------------------------------------------------------------- + case TypeClass_SEQUENCE: + { + if (aSourceClass==TypeClass_SEQUENCE) + { + if( aSourceType == aDestType ) + return rVal; + + TypeDescription aSourceTD( aSourceType ); + TypeDescription aDestTD( aDestType ); + typelib_TypeDescription * pSourceElementTD = 0; + TYPELIB_DANGER_GET( + &pSourceElementTD, + ((typelib_IndirectTypeDescription *)aSourceTD.get())->pType ); + typelib_TypeDescription * pDestElementTD = 0; + TYPELIB_DANGER_GET( + &pDestElementTD, + ((typelib_IndirectTypeDescription *)aDestTD.get())->pType ); + + sal_uInt32 nPos = (*(const uno_Sequence * const *)rVal.getValue())->nElements; + uno_Sequence * pRet = 0; + uno_sequence_construct( + &pRet, aDestTD.get(), 0, nPos, + reinterpret_cast< uno_AcquireFunc >(cpp_acquire) ); + aRet.setValue( &pRet, aDestTD.get() ); + uno_destructData( + &pRet, aDestTD.get(), + reinterpret_cast< uno_ReleaseFunc >(cpp_release) ); + // decr ref count + + char * pDestElements = (*(uno_Sequence * const *)aRet.getValue())->elements; + const char * pSourceElements = + (*(const uno_Sequence * const *)rVal.getValue())->elements; + + while (nPos--) + { + char * pDestPos = pDestElements + (nPos * pDestElementTD->nSize); + const char * pSourcePos = pSourceElements + (nPos * pSourceElementTD->nSize); + + Any aElement( + convertTo( Any( pSourcePos, pSourceElementTD ), pDestElementTD->pWeakRef ) ); + + if (!uno_assignData( + pDestPos, pDestElementTD, + (pDestElementTD->eTypeClass == typelib_TypeClass_ANY + ? &aElement + : const_cast< void * >( aElement.getValue() )), + pDestElementTD, + reinterpret_cast< uno_QueryInterfaceFunc >( + cpp_queryInterface), + reinterpret_cast< uno_AcquireFunc >(cpp_acquire), + reinterpret_cast< uno_ReleaseFunc >(cpp_release) )) + { + OSL_ASSERT( false ); + } + } + TYPELIB_DANGER_RELEASE( pDestElementTD ); + TYPELIB_DANGER_RELEASE( pSourceElementTD ); + } + break; + } + // --- to ENUM ------------------------------------------------------------------------------ + case TypeClass_ENUM: + { + TypeDescription aEnumTD( aDestType ); + aEnumTD.makeComplete(); + sal_Int32 nPos = -1; + + if (aSourceClass==TypeClass_STRING) + { + for ( nPos = ((typelib_EnumTypeDescription *)aEnumTD.get())->nEnumValues; nPos--; ) + { + if (((const OUString *)rVal.getValue())->equalsIgnoreAsciiCase( + ((typelib_EnumTypeDescription *)aEnumTD.get())->ppEnumNames[nPos] )) + break; + } + } + else if (aSourceClass!=TypeClass_ENUM && // exclude some unwanted types for toHyper() + aSourceClass!=TypeClass_BOOLEAN && + aSourceClass!=TypeClass_CHAR) + { + sal_Int32 nEnumValue = (sal_Int32)toHyper( rVal, -(sal_Int64)0x80000000, 0x7fffffff ); + for ( nPos = ((typelib_EnumTypeDescription *)aEnumTD.get())->nEnumValues; nPos--; ) + { + if (nEnumValue == ((typelib_EnumTypeDescription *)aEnumTD.get())->pEnumValues[nPos]) + break; + } + } + + if (nPos >= 0) + { + aRet.setValue( + &((typelib_EnumTypeDescription *)aEnumTD.get())->pEnumValues[nPos], + aEnumTD.get() ); + } + else + { + throw CannotConvertException( + OUString( + RTL_CONSTASCII_USTRINGPARAM("value cannot be converted to demanded ENUM!") ), + Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_ENUM, 0 ); + } + break; + } + + default: + // else simple type conversion possible? + try + { + aRet = convertToSimpleType( rVal, aDestinationClass ); + } + catch (IllegalArgumentException &) + { + // ...FailReason::INVALID is thrown + } + } + + if (aRet.hasValue()) + return aRet; + + throw CannotConvertException( + OUString( RTL_CONSTASCII_USTRINGPARAM("conversion not possible!") ), + Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 ); +} + +//-------------------------------------------------------------------------------------------------- +Any TypeConverter_Impl::convertToSimpleType( const Any& rVal, TypeClass aDestinationClass ) + throw( IllegalArgumentException, CannotConvertException, RuntimeException ) +{ + switch (aDestinationClass) + { + // only simple Conversion of _simple_ types + case TypeClass_INTERFACE: + case TypeClass_SERVICE: + case TypeClass_STRUCT: + case TypeClass_TYPEDEF: + case TypeClass_UNION: + case TypeClass_EXCEPTION: + case TypeClass_ARRAY: + case TypeClass_SEQUENCE: + case TypeClass_ENUM: + case TypeClass_UNKNOWN: + case TypeClass_MODULE: + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("destination type is not simple!") ), + Reference< XInterface >(), (sal_Int16) 1 ); + default: + break; + } + + Type aSourceType = rVal.getValueType(); + TypeClass aSourceClass = aSourceType.getTypeClass(); + if (aDestinationClass == aSourceClass) + return rVal; + + Any aRet; + + // Convert to... + switch (aDestinationClass) + { + // --- to VOID ------------------------------------------------------------------------------ + case TypeClass_VOID: + return Any(); + + // --- to ANY ------------------------------------------------------------------------------- + case TypeClass_ANY: + return rVal; + + // --- to BOOL ------------------------------------------------------------------------------ + case TypeClass_BOOLEAN: + switch (aSourceClass) + { + default: + { + sal_Bool bTmp = (toDouble( rVal ) != 0.0); + aRet.setValue( &bTmp, getBooleanCppuType() ); + } + case TypeClass_ENUM: // exclude enums + break; + + case TypeClass_STRING: + { + const OUString & aStr = *(const OUString *)rVal.getValue(); + if (aStr.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("0") ) || + aStr.equalsIgnoreAsciiCase( OUString( RTL_CONSTASCII_USTRINGPARAM("false") ) )) + { + sal_Bool bFalse = sal_False; + aRet.setValue( &bFalse, getCppuBooleanType() ); + } + else if (aStr.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("1") ) || + aStr.equalsIgnoreAsciiCase( OUString( RTL_CONSTASCII_USTRINGPARAM("true") ) )) + { + sal_Bool bTrue = sal_True; + aRet.setValue( &bTrue, getCppuBooleanType() ); + } + else + { + throw CannotConvertException( + OUString( RTL_CONSTASCII_USTRINGPARAM("STRING has no boolean value!") ), + Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_BOOL, 0 ); + } + } + } + break; + + // --- to CHAR, BYTE ------------------------------------------------------------------------ + case TypeClass_CHAR: + { + if (aSourceClass==TypeClass_STRING) + { + if ((*(const OUString *)rVal.getValue()).getLength() == 1) // single char + aRet.setValue( (*(const OUString *)rVal.getValue()).getStr(), ::getCharCppuType() ); + } + else if (aSourceClass!=TypeClass_ENUM && // exclude enums, chars + aSourceClass!=TypeClass_CHAR) + { + sal_Unicode cRet = (sal_Unicode)toHyper( rVal, 0, 0xffff ); // range + aRet.setValue( &cRet, ::getCharCppuType() ); + } + break; + } + case TypeClass_BYTE: + aRet <<= (sal_Int8)( toHyper( rVal, -(sal_Int64)0x80, 0x7f ) ); + break; + + // --- to SHORT, UNSIGNED SHORT ------------------------------------------------------------- + case TypeClass_SHORT: + aRet <<= (sal_Int16)( toHyper( rVal, -(sal_Int64)0x8000, 0x7fff ) ); + break; + case TypeClass_UNSIGNED_SHORT: + aRet <<= (sal_uInt16)( toHyper( rVal, 0, 0xffff ) ); + break; + + // --- to LONG, UNSIGNED LONG --------------------------------------------------------------- + case TypeClass_LONG: + aRet <<= (sal_Int32)( toHyper( rVal, -(sal_Int64)0x80000000, 0x7fffffff ) ); + break; + case TypeClass_UNSIGNED_LONG: + aRet <<= (sal_uInt32)( toHyper( rVal, 0, 0xffffffff ) ); + break; + + // --- to HYPER, UNSIGNED HYPER-------------------------------------------- + case TypeClass_HYPER: + aRet <<= toHyper( rVal, SAL_INT64_MIN, SAL_INT64_MAX ); + break; + case TypeClass_UNSIGNED_HYPER: + aRet <<= (sal_uInt64)( toHyper( rVal, 0, SAL_UINT64_MAX ) ); + break; + + // --- to FLOAT, DOUBLE --------------------------------------------------------------------- + case TypeClass_FLOAT: + aRet <<= (float)( toDouble( rVal, -FLT_MAX, FLT_MAX ) ); + break; + case TypeClass_DOUBLE: + aRet <<= (double)( toDouble( rVal, -DBL_MAX, DBL_MAX ) ); + break; + + // --- to STRING ---------------------------------------------------------------------------- + case TypeClass_STRING: + switch (aSourceClass) + { + case TypeClass_ENUM: + { + TypeDescription aEnumTD( aSourceType ); + aEnumTD.makeComplete(); + sal_Int32 nPos; + sal_Int32 nEnumValue = *(sal_Int32 *)rVal.getValue(); + for ( nPos = ((typelib_EnumTypeDescription *)aEnumTD.get())->nEnumValues; nPos--; ) + { + if (nEnumValue == ((typelib_EnumTypeDescription *)aEnumTD.get())->pEnumValues[nPos]) + break; + } + if (nPos >= 0) + { + aRet.setValue( + &((typelib_EnumTypeDescription *)aEnumTD.get())->ppEnumNames[nPos], + ::getCppuType( (const OUString *)0 ) ); + } + else + { + throw CannotConvertException( + OUString( RTL_CONSTASCII_USTRINGPARAM("value is not ENUM!") ), + Reference< XInterface >(), aDestinationClass, FailReason::IS_NOT_ENUM, 0 ); + } + break; + } + + case TypeClass_BOOLEAN: + aRet <<= OUString::createFromAscii( (*(sal_Bool *)rVal.getValue() ? "true" : "false") ); + break; + case TypeClass_CHAR: + aRet <<= OUString( (sal_Unicode *)rVal.getValue(), 1 ); + break; + + case TypeClass_BYTE: + aRet <<= OUString::valueOf( (sal_Int32)*(sal_Int8 const *)rVal.getValue() ); + break; + case TypeClass_SHORT: + aRet <<= OUString::valueOf( (sal_Int32)*(sal_Int16 const *)rVal.getValue() ); + break; + case TypeClass_UNSIGNED_SHORT: + aRet <<= OUString::valueOf( (sal_Int32)*(sal_uInt16 const *)rVal.getValue() ); + break; + case TypeClass_LONG: + aRet <<= OUString::valueOf( *(sal_Int32 const *)rVal.getValue() ); + break; + case TypeClass_UNSIGNED_LONG: + aRet <<= OUString::valueOf( (sal_Int64)*(sal_uInt32 const *)rVal.getValue() ); + break; + case TypeClass_HYPER: + aRet <<= OUString::valueOf( *(sal_Int64 const *)rVal.getValue() ); + break; +// case TypeClass_UNSIGNED_HYPER: +// aRet <<= OUString::valueOf( (sal_Int64)*(sal_uInt64 const *)rVal.getValue() ); +// break; + // handle unsigned hyper like double + + default: + aRet <<= OUString::valueOf( toDouble( rVal ) ); + } + break; + + default: + OSL_ASSERT(false); + break; + } + + if (aRet.hasValue()) + return aRet; + + throw CannotConvertException( + OUString( RTL_CONSTASCII_USTRINGPARAM("conversion not possible!") ), + Reference< XInterface >(), aDestinationClass, FailReason::INVALID, 0 ); +} +} + +namespace stoc_services +{ +//************************************************************************* +Reference< XInterface > SAL_CALL TypeConverter_Impl_CreateInstance( + const Reference< XComponentContext > & ) + throw( RuntimeException ) +{ + static Reference< XInterface > s_ref( (OWeakObject *) new stoc_tcv::TypeConverter_Impl() ); + return s_ref; +} +} + diff --git a/stoc/source/typeconv/makefile.mk b/stoc/source/typeconv/makefile.mk new file mode 100644 index 000000000000..e84f51889b98 --- /dev/null +++ b/stoc/source/typeconv/makefile.mk @@ -0,0 +1,48 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME=stoc +TARGET = typeconverter +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +DLLPRE = + +# ------------------------------------------------------------------ + +.INCLUDE : ..$/cppumaker.mk + +SLOFILES= \ + $(SLO)$/convert.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/stoc/source/uriproc/ExternalUriReferenceTranslator.cxx b/stoc/source/uriproc/ExternalUriReferenceTranslator.cxx new file mode 100644 index 000000000000..b11ba0fc0df2 --- /dev/null +++ b/stoc/source/uriproc/ExternalUriReferenceTranslator.cxx @@ -0,0 +1,240 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include "stocservices.hxx" + +#include "supportsService.hxx" + +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/uri/XExternalUriReferenceTranslator.hpp" +#include "cppuhelper/implbase2.hxx" +#include "cppuhelper/weak.hxx" +#include "osl/thread.h" +#include "rtl/string.h" +#include "rtl/textenc.h" +#include "rtl/uri.h" +#include "rtl/uri.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.hxx" +#include "sal/types.h" + +#include <new> + +namespace css = com::sun::star; + +namespace { + +class Translator: public cppu::WeakImplHelper2< + css::lang::XServiceInfo, css::uri::XExternalUriReferenceTranslator > +{ +public: + explicit Translator( + css::uno::Reference< css::uno::XComponentContext > const & context): + m_context(context) {} + + virtual rtl::OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & serviceName) + throw (css::uno::RuntimeException); + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames() throw (css::uno::RuntimeException); + + virtual rtl::OUString SAL_CALL + translateToInternal(rtl::OUString const & externalUriReference) + throw (css::uno::RuntimeException); + + virtual rtl::OUString SAL_CALL + translateToExternal(rtl::OUString const & internalUriReference) + throw (css::uno::RuntimeException); + +private: + Translator(Translator &); // not implemented + void operator =(Translator); // not implemented + + virtual ~Translator() {} + + css::uno::Reference< css::uno::XComponentContext > m_context; +}; + +rtl::OUString Translator::getImplementationName() + throw (css::uno::RuntimeException) +{ + return + stoc_services::ExternalUriReferenceTranslator::getImplementationName(); +} + +sal_Bool Translator::supportsService(rtl::OUString const & serviceName) + throw (css::uno::RuntimeException) +{ + return stoc::uriproc::supportsService( + getSupportedServiceNames(), serviceName); +} + +css::uno::Sequence< rtl::OUString > Translator::getSupportedServiceNames() + throw (css::uno::RuntimeException) +{ + return stoc_services::ExternalUriReferenceTranslator:: + getSupportedServiceNames(); +} + +rtl::OUString Translator::translateToInternal( + rtl::OUString const & externalUriReference) + throw (css::uno::RuntimeException) +{ + if (!externalUriReference.matchIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM("file:/"))) + { + return externalUriReference; + } + sal_Int32 i = RTL_CONSTASCII_LENGTH("file:"); + rtl::OUStringBuffer buf; + buf.append(externalUriReference.getStr(), i); + // Some environments (e.g., Java) produce illegal file URLs without an + // authority part; treat them as having an empty authority part: + if (!externalUriReference.matchAsciiL(RTL_CONSTASCII_STRINGPARAM("//"), i)) + { + buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); + } + rtl_TextEncoding encoding = osl_getThreadTextEncoding(); + for (bool path = true;;) { + sal_Int32 j = i; + while (j != externalUriReference.getLength() + && externalUriReference[j] != '#' + && (!path || externalUriReference[j] != '/')) + { + ++j; + } + if (j != i) { + rtl::OUString seg( + rtl::Uri::encode( + rtl::Uri::decode( + externalUriReference.copy(i, j - i), + rtl_UriDecodeStrict, encoding), + rtl_UriCharClassPchar, rtl_UriEncodeStrict, + RTL_TEXTENCODING_UTF8)); + if (seg.getLength() == 0) { + return rtl::OUString(); + } + buf.append(seg); + } + if (j == externalUriReference.getLength()) { + break; + } + buf.append(externalUriReference[j]); + path = externalUriReference[j] == '/'; + i = j + 1; + } + return buf.makeStringAndClear(); +} + +rtl::OUString Translator::translateToExternal( + rtl::OUString const & internalUriReference) + throw (css::uno::RuntimeException) +{ + if (!internalUriReference.matchIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM("file://"))) + { + return internalUriReference; + } + sal_Int32 i = RTL_CONSTASCII_LENGTH("file://"); + rtl::OUStringBuffer buf; + buf.append(internalUriReference.getStr(), i); + rtl_TextEncoding encoding = osl_getThreadTextEncoding(); + for (bool path = true;;) { + sal_Int32 j = i; + while (j != internalUriReference.getLength() + && internalUriReference[j] != '#' + && (!path || internalUriReference[j] != '/')) + { + ++j; + } + if (j != i) { + // Use rtl_UriDecodeToIuri -> rtl_UriEncodeStrictKeepEscapes instead + // of rtl_UriDecodeStrict -> rtl_UriEncodeStrict, so that spurious + // non--UTF-8 octets like "%FE" are copied verbatim: + rtl::OUString seg( + rtl::Uri::encode( + rtl::Uri::decode( + internalUriReference.copy(i, j - i), + rtl_UriDecodeToIuri, RTL_TEXTENCODING_UTF8), + rtl_UriCharClassPchar, rtl_UriEncodeStrictKeepEscapes, + encoding)); + if (seg.getLength() == 0) { + return rtl::OUString(); + } + buf.append(seg); + } + if (j == internalUriReference.getLength()) { + break; + } + buf.append(internalUriReference[j]); + path = internalUriReference[j] == '/'; + i = j + 1; + } + return buf.makeStringAndClear(); +} + +} + +namespace stoc_services { namespace ExternalUriReferenceTranslator { + +css::uno::Reference< css::uno::XInterface > create( + css::uno::Reference< css::uno::XComponentContext > const & context) + SAL_THROW((css::uno::Exception)) +{ + try { + return static_cast< cppu::OWeakObject * >(new Translator(context)); + } catch (std::bad_alloc &) { + throw css::uno::RuntimeException( + rtl::OUString::createFromAscii("std::bad_alloc"), 0); + } +} + +rtl::OUString getImplementationName() { + return rtl::OUString::createFromAscii( + "com.sun.star.comp.uri.ExternalUriReferenceTranslator"); +} + +css::uno::Sequence< rtl::OUString > getSupportedServiceNames() { + css::uno::Sequence< rtl::OUString > s(1); + s[0] = rtl::OUString::createFromAscii( + "com.sun.star.uri.ExternalUriReferenceTranslator"); + return s; +} + +} } diff --git a/stoc/source/uriproc/ExternalUriReferenceTranslator.hxx b/stoc/source/uriproc/ExternalUriReferenceTranslator.hxx new file mode 100644 index 000000000000..60b17bf39a6f --- /dev/null +++ b/stoc/source/uriproc/ExternalUriReferenceTranslator.hxx @@ -0,0 +1,59 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_stoc_source_uriproc_ExternalUriReferenceTranslator_hxx +#define INCLUDED_stoc_source_uriproc_ExternalUriReferenceTranslator_hxx + +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "sal/types.h" + +namespace com { namespace sun { namespace star { namespace uno { + class XComponentContext; + class XInterface; +} } } } +namespace rtl { class OUString; } + +namespace stoc { namespace uriproc { + +namespace ExternalUriReferenceTranslator { + com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL + create( + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + const & context) + SAL_THROW((com::sun::star::uno::Exception)); + + rtl::OUString SAL_CALL getImplementationName(); + + com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames(); +} + +} } + +#endif diff --git a/stoc/source/uriproc/UriReference.cxx b/stoc/source/uriproc/UriReference.cxx new file mode 100644 index 000000000000..12654f4d6b90 --- /dev/null +++ b/stoc/source/uriproc/UriReference.cxx @@ -0,0 +1,206 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include "UriReference.hxx" + +#include "osl/diagnose.h" +#include "osl/mutex.hxx" +#include "rtl/string.h" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.hxx" +#include "sal/types.h" + +namespace css = com::sun::star; +using stoc::uriproc::UriReference; + +UriReference::UriReference( + rtl::OUString const & scheme, bool bIsHierarchical, bool bHasAuthority, + rtl::OUString const & authority, rtl::OUString const & path, + bool bHasQuery, rtl::OUString const & query): + m_scheme(scheme), + m_authority(authority), + m_path(path), + m_query(query), + m_isHierarchical(bIsHierarchical), + m_hasAuthority(bHasAuthority), + m_hasQuery(bHasQuery), + m_hasFragment(false) +{ + OSL_ASSERT(scheme.getLength() != 0 || bIsHierarchical); + OSL_ASSERT(!bHasAuthority || bIsHierarchical); + OSL_ASSERT(authority.getLength() == 0 || bHasAuthority); + OSL_ASSERT(!bHasQuery || bIsHierarchical); + OSL_ASSERT(query.getLength() == 0 || bHasQuery); +} + +UriReference::~UriReference() {} + +rtl::OUString UriReference::getUriReference() throw (css::uno::RuntimeException) +{ + osl::MutexGuard g(m_mutex); + rtl::OUStringBuffer buf; + if (m_scheme.getLength() != 0) { + buf.append(m_scheme); + buf.append(static_cast< sal_Unicode >(':')); + } + appendSchemeSpecificPart(buf); + if (m_hasFragment) { + buf.append(static_cast< sal_Unicode >('#')); + buf.append(m_fragment); + } + return buf.makeStringAndClear(); +} + +sal_Bool UriReference::isAbsolute() throw (css::uno::RuntimeException) { + return m_scheme.getLength() != 0; +} + +rtl::OUString UriReference::getScheme() throw (css::uno::RuntimeException) { + return m_scheme; +} + +rtl::OUString UriReference::getSchemeSpecificPart() + throw (css::uno::RuntimeException) +{ + osl::MutexGuard g(m_mutex); + rtl::OUStringBuffer buf; + appendSchemeSpecificPart(buf); + return buf.makeStringAndClear(); +} + +sal_Bool UriReference::isHierarchical() throw (css::uno::RuntimeException) { + osl::MutexGuard g(m_mutex); + return m_isHierarchical; +} + +sal_Bool UriReference::hasAuthority() throw (css::uno::RuntimeException) { + osl::MutexGuard g(m_mutex); + return m_hasAuthority; +} + +rtl::OUString UriReference::getAuthority() throw (css::uno::RuntimeException) { + osl::MutexGuard g(m_mutex); + return m_authority; +} + +rtl::OUString UriReference::getPath() throw (css::uno::RuntimeException) { + osl::MutexGuard g(m_mutex); + return m_path; +} + +sal_Bool UriReference::hasRelativePath() throw (css::uno::RuntimeException) { + osl::MutexGuard g(m_mutex); + return m_isHierarchical && !m_hasAuthority + && (m_path.getLength() == 0 || m_path[0] != '/'); +} + +sal_Int32 UriReference::getPathSegmentCount() throw (css::uno::RuntimeException) +{ + osl::MutexGuard g(m_mutex); + if (!m_isHierarchical || m_path.getLength() == 0) { + return 0; + } else { + sal_Int32 n = m_path[0] == '/' ? 0 : 1; + for (sal_Int32 i = 0;; ++i) { + i = m_path.indexOf('/', i); + if (i < 0) { + break; + } + ++n; + } + return n; + } +} + +rtl::OUString UriReference::getPathSegment(sal_Int32 index) + throw (css::uno::RuntimeException) +{ + osl::MutexGuard g(m_mutex); + if (m_isHierarchical && m_path.getLength() != 0 && index >= 0) { + for (sal_Int32 i = m_path[0] == '/' ? 1 : 0;; ++i) { + if (index-- == 0) { + sal_Int32 j = m_path.indexOf('/', i); + return j < 0 ? m_path.copy(i) : m_path.copy(i, j - i); + } + i = m_path.indexOf('/', i); + if (i < 0) { + break; + } + } + } + return rtl::OUString(); +} + +sal_Bool UriReference::hasQuery() throw (css::uno::RuntimeException) { + osl::MutexGuard g(m_mutex); + return m_hasQuery; +} + +rtl::OUString UriReference::getQuery() throw (css::uno::RuntimeException) { + osl::MutexGuard g(m_mutex); + return m_query; +} + +sal_Bool UriReference::hasFragment() throw (css::uno::RuntimeException) { + osl::MutexGuard g(m_mutex); + return m_hasFragment; +} + +rtl::OUString UriReference::getFragment() throw (css::uno::RuntimeException) { + osl::MutexGuard g(m_mutex); + return m_fragment; +} + +void UriReference::setFragment(rtl::OUString const & fragment) + throw (css::uno::RuntimeException) +{ + osl::MutexGuard g(m_mutex); + m_hasFragment = true; + m_fragment = fragment; +} + +void UriReference::clearFragment() throw (css::uno::RuntimeException) { + osl::MutexGuard g(m_mutex); + m_hasFragment = false; + m_fragment = rtl::OUString(); +} + +void UriReference::appendSchemeSpecificPart(rtl::OUStringBuffer & buffer) const +{ + if (m_hasAuthority) { + buffer.appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); + buffer.append(m_authority); + } + buffer.append(m_path); + if (m_hasQuery) { + buffer.append(static_cast< sal_Unicode >('?')); + buffer.append(m_query); + } +} diff --git a/stoc/source/uriproc/UriReference.hxx b/stoc/source/uriproc/UriReference.hxx new file mode 100644 index 000000000000..38b8f5518fbf --- /dev/null +++ b/stoc/source/uriproc/UriReference.hxx @@ -0,0 +1,108 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_stoc_source_uriproc_UriReference_hxx +#define INCLUDED_stoc_source_uriproc_UriReference_hxx + +#include "com/sun/star/uno/RuntimeException.hpp" +#include "osl/mutex.hxx" +#include "rtl/ustring.hxx" +#include "sal/types.h" + +namespace rtl { class OUStringBuffer; } + +namespace stoc { namespace uriproc { + +class UriReference { +public: + UriReference( + rtl::OUString const & scheme, bool isHierarchical, bool hasAuthority, + rtl::OUString const & authority, rtl::OUString const & path, + bool hasQuery, rtl::OUString const & query); + + ~UriReference(); + + rtl::OUString getUriReference() + throw (com::sun::star::uno::RuntimeException); + + sal_Bool isAbsolute() throw (com::sun::star::uno::RuntimeException); + + rtl::OUString getScheme() throw (com::sun::star::uno::RuntimeException); + + rtl::OUString getSchemeSpecificPart() + throw (com::sun::star::uno::RuntimeException); + + sal_Bool isHierarchical() throw (com::sun::star::uno::RuntimeException); + + sal_Bool hasAuthority() throw (com::sun::star::uno::RuntimeException); + + rtl::OUString getAuthority() throw (com::sun::star::uno::RuntimeException); + + rtl::OUString getPath() throw (com::sun::star::uno::RuntimeException); + + sal_Bool hasRelativePath() throw (com::sun::star::uno::RuntimeException); + + sal_Int32 getPathSegmentCount() + throw (com::sun::star::uno::RuntimeException); + + rtl::OUString getPathSegment(sal_Int32 index) + throw (com::sun::star::uno::RuntimeException); + + sal_Bool hasQuery() throw (com::sun::star::uno::RuntimeException); + + rtl::OUString getQuery() throw (com::sun::star::uno::RuntimeException); + + sal_Bool hasFragment() throw (com::sun::star::uno::RuntimeException); + + rtl::OUString getFragment() throw (com::sun::star::uno::RuntimeException); + + void setFragment(rtl::OUString const & fragment) + throw (com::sun::star::uno::RuntimeException); + + void clearFragment() throw (com::sun::star::uno::RuntimeException); + + osl::Mutex m_mutex; + rtl::OUString m_scheme; + rtl::OUString m_authority; + rtl::OUString m_path; + rtl::OUString m_query; + rtl::OUString m_fragment; + bool m_isHierarchical; + bool m_hasAuthority; + bool m_hasQuery; + bool m_hasFragment; + +private: + UriReference(UriReference &); // not implemented + void operator =(UriReference); // not implemented + + void appendSchemeSpecificPart(rtl::OUStringBuffer & buffer) const; +}; + +} } + +#endif diff --git a/stoc/source/uriproc/UriReferenceFactory.cxx b/stoc/source/uriproc/UriReferenceFactory.cxx new file mode 100644 index 000000000000..89367ade36cf --- /dev/null +++ b/stoc/source/uriproc/UriReferenceFactory.cxx @@ -0,0 +1,724 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include "stocservices.hxx" + +#include "UriReference.hxx" +#include "supportsService.hxx" + +#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp" +#include "com/sun/star/lang/XMultiComponentFactory.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/uno/Any.hxx" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/uri/RelativeUriExcessParentSegments.hpp" +#include "com/sun/star/uri/XUriReference.hpp" +#include "com/sun/star/uri/XUriReferenceFactory.hpp" +#include "com/sun/star/uri/XUriSchemeParser.hpp" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/implbase2.hxx" +#include "cppuhelper/weak.hxx" +#include "osl/diagnose.h" +#include "rtl/string.h" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.hxx" +#include "sal/types.h" + +#include <algorithm> +#include /*MSVC trouble: <cstdlib>*/ <stdlib.h> +#include <new> +#include <vector> + +namespace css = com::sun::star; + +namespace { + +bool isDigit(sal_Unicode c) { //TODO: generally available? + return c >= '0' && c <= '9'; +} + +bool isUpperCase(sal_Unicode c) { //TODO: generally available? + return c >= 'A' && c <= 'Z'; +} + +bool isLowerCase(sal_Unicode c) { //TODO: generally available? + return c >= 'a' && c <= 'z'; +} + +bool isAlpha(sal_Unicode c) { //TODO: generally available? + return isUpperCase(c) || isLowerCase(c); +} + +bool isHexDigit(sal_Unicode c) { //TODO: generally available? + return isDigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); +} + +sal_Unicode toLowerCase(sal_Unicode c) { //TODO: generally available? + return isUpperCase(c) ? c + ('a' - 'A') : c; +} + +bool equalIgnoreCase(sal_Unicode c1, sal_Unicode c2) { + //TODO: generally available? + return toLowerCase(c1) == toLowerCase(c2); +} + +bool equalIgnoreEscapeCase(rtl::OUString const & s1, rtl::OUString const & s2) { + if (s1.getLength() == s2.getLength()) { + for (sal_Int32 i = 0; i < s1.getLength();) { + if (s1[i] == '%' && s2[i] == '%' && s1.getLength() - i > 2 + && isHexDigit(s1[i + 1]) && isHexDigit(s1[i + 2]) + && isHexDigit(s2[i + 1]) && isHexDigit(s2[i + 2]) + && equalIgnoreCase(s1[i + 1], s2[i + 1]) + && equalIgnoreCase(s1[i + 2], s2[i + 2])) + { + i += 3; + } else if (s1[i] != s2[i]) { + return false; + } else { + ++i; + } + } + return true; + } else { + return false; + } +} + +sal_Int32 parseScheme(rtl::OUString const & uriReference) { + if (uriReference.getLength() >= 2 && isAlpha(uriReference[0])) { + for (sal_Int32 i = 0; i < uriReference.getLength(); ++i) { + sal_Unicode c = uriReference[i]; + if (c == ':') { + return i; + } else if (!isAlpha(c) && !isDigit(c) && c != '+' && c != '-' + && c != '.') + { + break; + } + } + } + return -1; +} + +class UriReference: public cppu::WeakImplHelper1< css::uri::XUriReference > { +public: + UriReference( + rtl::OUString const & scheme, bool bIsHierarchical, bool bHasAuthority, + rtl::OUString const & authority, rtl::OUString const & path, + bool bHasQuery, rtl::OUString const & query): + m_base( + scheme, bIsHierarchical, bHasAuthority, authority, path, bHasQuery, + query) + {} + + virtual rtl::OUString SAL_CALL getUriReference() + throw (com::sun::star::uno::RuntimeException) + { return m_base.getUriReference(); } + + virtual sal_Bool SAL_CALL isAbsolute() + throw (com::sun::star::uno::RuntimeException) + { return m_base.isAbsolute(); } + + virtual rtl::OUString SAL_CALL getScheme() + throw (com::sun::star::uno::RuntimeException) + { return m_base.getScheme(); } + + virtual rtl::OUString SAL_CALL getSchemeSpecificPart() + throw (com::sun::star::uno::RuntimeException) + { return m_base.getSchemeSpecificPart(); } + + virtual sal_Bool SAL_CALL isHierarchical() + throw (com::sun::star::uno::RuntimeException) + { return m_base.isHierarchical(); } + + virtual sal_Bool SAL_CALL hasAuthority() + throw (com::sun::star::uno::RuntimeException) + { return m_base.hasAuthority(); } + + virtual rtl::OUString SAL_CALL getAuthority() + throw (com::sun::star::uno::RuntimeException) + { return m_base.getAuthority(); } + + virtual rtl::OUString SAL_CALL getPath() + throw (com::sun::star::uno::RuntimeException) + { return m_base.getPath(); } + + virtual sal_Bool SAL_CALL hasRelativePath() + throw (com::sun::star::uno::RuntimeException) + { return m_base.hasRelativePath(); } + + virtual sal_Int32 SAL_CALL getPathSegmentCount() + throw (com::sun::star::uno::RuntimeException) + { return m_base.getPathSegmentCount(); } + + virtual rtl::OUString SAL_CALL getPathSegment(sal_Int32 index) + throw (com::sun::star::uno::RuntimeException) + { return m_base.getPathSegment(index); } + + virtual sal_Bool SAL_CALL hasQuery() + throw (com::sun::star::uno::RuntimeException) + { return m_base.hasQuery(); } + + virtual rtl::OUString SAL_CALL getQuery() + throw (com::sun::star::uno::RuntimeException) + { return m_base.getQuery(); } + + virtual sal_Bool SAL_CALL hasFragment() + throw (com::sun::star::uno::RuntimeException) + { return m_base.hasFragment(); } + + virtual rtl::OUString SAL_CALL getFragment() + throw (com::sun::star::uno::RuntimeException) + { return m_base.getFragment(); } + + virtual void SAL_CALL setFragment(rtl::OUString const & fragment) + throw (com::sun::star::uno::RuntimeException) + { m_base.setFragment(fragment); } + + virtual void SAL_CALL clearFragment() + throw (com::sun::star::uno::RuntimeException) + { m_base.clearFragment(); } + +private: + UriReference(UriReference &); // not implemented + void operator =(UriReference); // not implemented + + virtual ~UriReference() {} + + stoc::uriproc::UriReference m_base; +}; + +// throws std::bad_alloc +css::uno::Reference< css::uri::XUriReference > parseGeneric( + rtl::OUString const & scheme, rtl::OUString const & schemeSpecificPart) +{ + bool isAbsolute = scheme.getLength() != 0; + bool isHierarchical + = !isAbsolute + || (schemeSpecificPart.getLength() > 0 && schemeSpecificPart[0] == '/'); + bool hasAuthority = false; + rtl::OUString authority; + rtl::OUString path; + bool hasQuery = false; + rtl::OUString query; + if (isHierarchical) { + sal_Int32 len = schemeSpecificPart.getLength(); + sal_Int32 i = 0; + if (len - i >= 2 && schemeSpecificPart[i] == '/' + && schemeSpecificPart[i + 1] == '/') + { + i += 2; + sal_Int32 n = i; + while (i < len && schemeSpecificPart[i] != '/' + && schemeSpecificPart[i] != '?') { + ++i; + } + hasAuthority = true; + authority = schemeSpecificPart.copy(n, i - n); + } + sal_Int32 n = i; + i = schemeSpecificPart.indexOf('?', i); + if (i == -1) { + i = len; + } + path = schemeSpecificPart.copy(n, i - n); + if (i != len) { + hasQuery = true; + query = schemeSpecificPart.copy(i + 1); + } + } else { + if (schemeSpecificPart.getLength() == 0) { + // The scheme-specific part of an opaque URI must not be empty: + return 0; + } + path = schemeSpecificPart; + } + return new UriReference( + scheme, isHierarchical, hasAuthority, authority, path, hasQuery, query); +} + +typedef std::vector< sal_Int32 > Segments; + +void processSegments( + Segments & segments, + css::uno::Reference< css::uri::XUriReference > const & uriReference, + bool base, bool processSpecialSegments) +{ + sal_Int32 count = uriReference->getPathSegmentCount() - (base ? 1 : 0); + OSL_ASSERT(count <= SAL_MAX_INT32 - 1 && -count >= SAL_MIN_INT32 + 1); + for (sal_Int32 i = 0; i < count; ++i) { + if (processSpecialSegments) { + rtl::OUString segment(uriReference->getPathSegment(i)); + if (segment.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("."))) { + if (!base && i == count - 1) { + segments.push_back(0); + } + continue; + } else if (segment.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(".."))) { + if (segments.empty() + || /*MSVC trouble: std::*/abs(segments.back()) == 1) + { + segments.push_back(base ? -1 : 1); + } else { + segments.pop_back(); + } + continue; + } + } + segments.push_back(base ? -(i + 2) : i + 2); + } +} + +class Factory: public cppu::WeakImplHelper2< + css::lang::XServiceInfo, css::uri::XUriReferenceFactory > +{ +public: + explicit Factory( + css::uno::Reference< css::uno::XComponentContext > const & context): + m_context(context) {} + + virtual rtl::OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & serviceName) + throw (css::uno::RuntimeException); + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames() throw (css::uno::RuntimeException); + + virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL + parse(rtl::OUString const & uriReference) + throw (css::uno::RuntimeException); + + virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL + makeAbsolute( + css::uno::Reference< css::uri::XUriReference > const & baseUriReference, + css::uno::Reference< css::uri::XUriReference > const & uriReference, + sal_Bool processSpecialBaseSegments, + css::uri::RelativeUriExcessParentSegments excessParentSegments) + throw (css::uno::RuntimeException); + + virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL + makeRelative( + css::uno::Reference< css::uri::XUriReference > const & baseUriReference, + css::uno::Reference< css::uri::XUriReference > const & uriReference, + sal_Bool preferAuthorityOverRelativePath, + sal_Bool preferAbsoluteOverRelativePath, + sal_Bool encodeRetainedSpecialSegments) + throw (css::uno::RuntimeException); + +private: + Factory(Factory &); // not implemented + void operator =(Factory); // not implemented + + virtual ~Factory() {} + + css::uno::Reference< css::uri::XUriReference > clone( + css::uno::Reference< css::uri::XUriReference > const & uriReference) + { return parse(uriReference->getUriReference()); } + + css::uno::Reference< css::uno::XComponentContext > m_context; +}; + +rtl::OUString Factory::getImplementationName() + throw (css::uno::RuntimeException) +{ + return stoc_services::UriReferenceFactory::getImplementationName(); +} + +sal_Bool Factory::supportsService(rtl::OUString const & serviceName) + throw (css::uno::RuntimeException) +{ + return stoc::uriproc::supportsService( + getSupportedServiceNames(), serviceName); +} + +css::uno::Sequence< rtl::OUString > Factory::getSupportedServiceNames() + throw (css::uno::RuntimeException) +{ + return stoc_services::UriReferenceFactory::getSupportedServiceNames(); +} + +css::uno::Reference< css::uri::XUriReference > Factory::parse( + rtl::OUString const & uriReference) throw (css::uno::RuntimeException) +{ + sal_Int32 fragment = uriReference.indexOf('#'); + if (fragment == -1) { + fragment = uriReference.getLength(); + } + rtl::OUString scheme; + rtl::OUString schemeSpecificPart; + rtl::OUString serviceName; + sal_Int32 n = parseScheme(uriReference); + OSL_ASSERT(n < fragment); + if (n >= 0) { + scheme = uriReference.copy(0, n); + schemeSpecificPart = uriReference.copy(n + 1, fragment - (n + 1)); + rtl::OUStringBuffer buf; + buf.appendAscii( + RTL_CONSTASCII_STRINGPARAM("com.sun.star.uri.UriSchemeParser_")); + for (sal_Int32 i = 0; i < scheme.getLength(); ++i) { + sal_Unicode c = scheme[i]; + if (isUpperCase(c)) { + buf.append(toLowerCase(c)); + } else if (c == '+') { + buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("PLUS")); + } else if (c == '-') { + buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("HYPHEN")); + } else if (c == '.') { + buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("DOT")); + } else { + OSL_ASSERT(isLowerCase(c) || isDigit(c)); + buf.append(c); + } + } + serviceName = buf.makeStringAndClear(); + } else { + schemeSpecificPart = uriReference.copy(0, fragment); + } + css::uno::Reference< css::uri::XUriSchemeParser > parser; + if (serviceName.getLength() != 0) { + css::uno::Reference< css::lang::XMultiComponentFactory > factory( + m_context->getServiceManager()); + if (factory.is()) { + css::uno::Reference< css::uno::XInterface > service; + try { + service = factory->createInstanceWithContext( + serviceName, m_context); + } catch (css::uno::RuntimeException &) { + throw; + } catch (css::uno::Exception & e) { + throw css::lang::WrappedTargetRuntimeException( + rtl::OUString::createFromAscii("creating service ") + + serviceName, + static_cast< cppu::OWeakObject * >(this), + css::uno::makeAny(e)); //TODO: preserve type of e + } + if (service.is()) { + parser = css::uno::Reference< css::uri::XUriSchemeParser >( + service, css::uno::UNO_QUERY_THROW); + } + } + } + css::uno::Reference< css::uri::XUriReference > uriRef; + if (parser.is()) { + uriRef = parser->parse(scheme, schemeSpecificPart); + } else { + try { + uriRef = parseGeneric(scheme, schemeSpecificPart); + } catch (std::bad_alloc &) { + throw css::uno::RuntimeException( + rtl::OUString::createFromAscii("std::bad_alloc"), + static_cast< cppu::OWeakObject * >(this)); + } + } + if (uriRef.is() && fragment != uriReference.getLength()) { + uriRef->setFragment(uriReference.copy(fragment + 1)); + } + return uriRef; +} + +css::uno::Reference< css::uri::XUriReference > Factory::makeAbsolute( + css::uno::Reference< css::uri::XUriReference > const & baseUriReference, + css::uno::Reference< css::uri::XUriReference > const & uriReference, + sal_Bool processSpecialBaseSegments, + css::uri::RelativeUriExcessParentSegments excessParentSegments) + throw (css::uno::RuntimeException) +{ + if (!baseUriReference.is() || !baseUriReference->isAbsolute() + || !baseUriReference->isHierarchical() || !uriReference.is()) { + return 0; + } else if (uriReference->isAbsolute()) { + return clone(uriReference); + } else if (!uriReference->hasAuthority() + && uriReference->getPath().getLength() == 0 + && !uriReference->hasQuery()) { + css::uno::Reference< css::uri::XUriReference > abs( + clone(baseUriReference)); + if (uriReference->hasFragment()) { + abs->setFragment(uriReference->getFragment()); + } else { + abs->clearFragment(); + } + return abs; + } else { + rtl::OUStringBuffer abs(baseUriReference->getScheme()); + abs.append(static_cast< sal_Unicode >(':')); + if (uriReference->hasAuthority()) { + abs.appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); + abs.append(uriReference->getAuthority()); + } else if (baseUriReference->hasAuthority()) { + abs.appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); + abs.append(baseUriReference->getAuthority()); + } + if (uriReference->hasRelativePath()) { + Segments segments; + processSegments( + segments, baseUriReference, true, processSpecialBaseSegments); + processSegments(segments, uriReference, false, true); + // If the path component of the base URI reference is empty (which + // implies that the base URI reference denotes a "root entity"), and + // the resulting URI reference denotes the same root entity, make + // sure the path component of the resulting URI reference is also + // empty (and not "/"). RFC 2396 is unclear about this, and I chose + // these rules for consistent results. + bool slash = baseUriReference->getPath().getLength() != 0; + if (slash) { + abs.append(static_cast< sal_Unicode >('/')); + } + for (Segments::iterator i(segments.begin()); i != segments.end(); + ++i) + { + if (*i < -1) { + rtl::OUString segment( + baseUriReference->getPathSegment(-(*i + 2))); + if (segment.getLength() != 0 || segments.size() > 1) { + if (!slash) { + abs.append(static_cast< sal_Unicode >('/')); + } + abs.append(segment); + slash = true; + abs.append(static_cast< sal_Unicode >('/')); + } + } else if (*i > 1) { + rtl::OUString segment(uriReference->getPathSegment(*i - 2)); + if (segment.getLength() != 0 || segments.size() > 1) { + if (!slash) { + abs.append(static_cast< sal_Unicode >('/')); + } + abs.append(segment); + slash = false; + } + } else if (*i == 0) { + if (segments.size() > 1 && !slash) { + abs.append(static_cast< sal_Unicode >('/')); + } + } else { + switch (excessParentSegments) { + case css::uri::RelativeUriExcessParentSegments_ERROR: + return 0; + + case css::uri::RelativeUriExcessParentSegments_RETAIN: + if (!slash) { + abs.append(static_cast< sal_Unicode >('/')); + } + abs.appendAscii(RTL_CONSTASCII_STRINGPARAM("..")); + slash = *i < 0; + if (slash) { + abs.append(static_cast< sal_Unicode >('/')); + } + break; + + case css::uri::RelativeUriExcessParentSegments_REMOVE: + break; + + default: + OSL_ASSERT(false); + break; + } + } + } + } else { + abs.append(uriReference->getPath()); + } + if (uriReference->hasQuery()) { + abs.append(static_cast< sal_Unicode >('?')); + abs.append(uriReference->getQuery()); + } + if (uriReference->hasFragment()) { + abs.append(static_cast< sal_Unicode >('#')); + abs.append(uriReference->getFragment()); + } + return parse(abs.makeStringAndClear()); + } +} + +css::uno::Reference< css::uri::XUriReference > Factory::makeRelative( + css::uno::Reference< css::uri::XUriReference > const & baseUriReference, + css::uno::Reference< css::uri::XUriReference > const & uriReference, + sal_Bool preferAuthorityOverRelativePath, + sal_Bool preferAbsoluteOverRelativePath, + sal_Bool encodeRetainedSpecialSegments) + throw (css::uno::RuntimeException) +{ + if (!baseUriReference.is() || !baseUriReference->isAbsolute() + || !baseUriReference->isHierarchical() || !uriReference.is()) { + return 0; + } else if (!uriReference->isAbsolute() || !uriReference->isHierarchical() + || !baseUriReference->getScheme().equalsIgnoreAsciiCase( + uriReference->getScheme())) { + return clone(uriReference); + } else { + rtl::OUStringBuffer rel; + bool omitQuery = false; + if ((baseUriReference->hasAuthority() != uriReference->hasAuthority()) + || !equalIgnoreEscapeCase( + baseUriReference->getAuthority(), + uriReference->getAuthority())) + { + if (uriReference->hasAuthority()) { + rel.appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); + rel.append(uriReference->getAuthority()); + } + rel.append(uriReference->getPath()); + } else if ((equalIgnoreEscapeCase( + baseUriReference->getPath(), uriReference->getPath()) + || (baseUriReference->getPath().getLength() <= 1 + && uriReference->getPath().getLength() <= 1)) + && baseUriReference->hasQuery() == uriReference->hasQuery() + && equalIgnoreEscapeCase( + baseUriReference->getQuery(), uriReference->getQuery())) + { + omitQuery = true; + } else { + sal_Int32 count1 = std::max< sal_Int32 >( + baseUriReference->getPathSegmentCount(), 1); + sal_Int32 count2 = std::max< sal_Int32 >( + uriReference->getPathSegmentCount(), 1); + sal_Int32 i = 0; + for (; i < std::min(count1, count2) - 1; ++i) { + if (!equalIgnoreEscapeCase( + baseUriReference->getPathSegment(i), + uriReference->getPathSegment(i))) + { + break; + } + } + if (i == 0 && preferAbsoluteOverRelativePath + && (preferAuthorityOverRelativePath + || !uriReference->getPath().matchAsciiL( + RTL_CONSTASCII_STRINGPARAM("//")))) + { + if (baseUriReference->getPath().getLength() > 1 + || uriReference->getPath().getLength() > 1) + { + if (uriReference->getPath().getLength() == 0) { + rel.append(static_cast< sal_Unicode >('/')); + } else { + OSL_ASSERT(uriReference->getPath()[0] == '/'); + if (uriReference->getPath().matchAsciiL( + RTL_CONSTASCII_STRINGPARAM("//"))) { + OSL_ASSERT(uriReference->hasAuthority()); + rel.appendAscii(RTL_CONSTASCII_STRINGPARAM("//")); + rel.append(uriReference->getAuthority()); + } + rel.append(uriReference->getPath()); + } + } + } else { + bool segments = false; + for (sal_Int32 j = i; j < count1 - 1; ++j) { + if (segments) { + rel.append(static_cast< sal_Unicode >('/')); + } + rel.appendAscii(RTL_CONSTASCII_STRINGPARAM("..")); + segments = true; + } + if (i < count2 - 1 + || (uriReference->getPathSegment(count2 - 1).getLength() + != 0)) + { + if (!segments + && (uriReference->getPathSegment(i).getLength() == 0 + || (parseScheme(uriReference->getPathSegment(i)) + >= 0))) + { + rel.append(static_cast< sal_Unicode >('.')); + segments = true; + } + for (; i < count2; ++i) { + if (segments) { + rel.append(static_cast< sal_Unicode >('/')); + } + rtl::OUString s(uriReference->getPathSegment(i)); + if (encodeRetainedSpecialSegments + && s.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("."))) + { + rel.appendAscii(RTL_CONSTASCII_STRINGPARAM("%2E")); + } else if (encodeRetainedSpecialSegments + && s.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM(".."))) + { + rel.appendAscii( + RTL_CONSTASCII_STRINGPARAM("%2E%2E")); + } else { + rel.append(s); + } + segments = true; + } + } + } + } + if (!omitQuery && uriReference->hasQuery()) { + rel.append(static_cast< sal_Unicode >('?')); + rel.append(uriReference->getQuery()); + } + if (uriReference->hasFragment()) { + rel.append(static_cast< sal_Unicode >('#')); + rel.append(uriReference->getFragment()); + } + return parse(rel.makeStringAndClear()); + } +} + +} + +namespace stoc_services { namespace UriReferenceFactory { + +css::uno::Reference< css::uno::XInterface > create( + css::uno::Reference< css::uno::XComponentContext > const & context) + SAL_THROW((css::uno::Exception)) +{ + try { + return static_cast< cppu::OWeakObject * >(new Factory(context)); + } catch (std::bad_alloc &) { + throw css::uno::RuntimeException( + rtl::OUString::createFromAscii("std::bad_alloc"), 0); + } +} + +rtl::OUString getImplementationName() { + return rtl::OUString::createFromAscii( + "com.sun.star.comp.uri.UriReferenceFactory"); +} + +css::uno::Sequence< rtl::OUString > getSupportedServiceNames() { + css::uno::Sequence< rtl::OUString > s(1); + s[0] = rtl::OUString::createFromAscii( + "com.sun.star.uri.UriReferenceFactory"); + return s; +} + +} } diff --git a/stoc/source/uriproc/UriReferenceFactory.hxx b/stoc/source/uriproc/UriReferenceFactory.hxx new file mode 100644 index 000000000000..0aca96fce962 --- /dev/null +++ b/stoc/source/uriproc/UriReferenceFactory.hxx @@ -0,0 +1,59 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_stoc_source_uriproc_UriReferenceFactory_hxx +#define INCLUDED_stoc_source_uriproc_UriReferenceFactory_hxx + +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "sal/types.h" + +namespace com { namespace sun { namespace star { namespace uno { + class XComponentContext; + class XInterface; +} } } } +namespace rtl { class OUString; } + +namespace stoc { namespace uriproc { + +namespace UriReferenceFactory { + com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL + create( + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + const & context) + SAL_THROW((com::sun::star::uno::Exception)); + + rtl::OUString SAL_CALL getImplementationName(); + + com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames(); +} + +} } + +#endif diff --git a/stoc/source/uriproc/UriSchemeParser_vndDOTsunDOTstarDOTexpand.cxx b/stoc/source/uriproc/UriSchemeParser_vndDOTsunDOTstarDOTexpand.cxx new file mode 100644 index 000000000000..a84a1200c953 --- /dev/null +++ b/stoc/source/uriproc/UriSchemeParser_vndDOTsunDOTstarDOTexpand.cxx @@ -0,0 +1,268 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include "sal/config.h" + +#include "stocservices.hxx" + +#include <new> + +#include "com/sun/star/lang/IllegalArgumentException.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/uri/XUriReference.hpp" +#include "com/sun/star/uri/XUriSchemeParser.hpp" +#include "com/sun/star/uri/XVndSunStarExpandUrlReference.hpp" +#include "com/sun/star/util/XMacroExpander.hpp" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/implbase2.hxx" +#include "cppuhelper/weak.hxx" +#include "rtl/textenc.h" +#include "rtl/uri.h" +#include "rtl/uri.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" + +#include "UriReference.hxx" +#include "supportsService.hxx" + +namespace { + +namespace css = ::com::sun::star; + +bool parseSchemeSpecificPart(::rtl::OUString const & part) { + // Liberally accepts both an empty opaque_part and an opaque_part that + // starts with a non-escaped "/": + return part.getLength() == 0 + || ((::rtl::Uri::decode( + part, ::rtl_UriDecodeStrict, RTL_TEXTENCODING_UTF8). + getLength()) + != 0); +} + +class UrlReference: + public ::cppu::WeakImplHelper1< css::uri::XVndSunStarExpandUrlReference > +{ +public: + UrlReference(::rtl::OUString const & scheme, ::rtl::OUString const & path): + base_( + scheme, false, false, ::rtl::OUString(), path, false, + ::rtl::OUString()) + {} + + virtual ::rtl::OUString SAL_CALL getUriReference() + throw (css::uno::RuntimeException) + { return base_.getUriReference(); } + + virtual ::sal_Bool SAL_CALL isAbsolute() throw (css::uno::RuntimeException) + { return base_.isAbsolute(); } + + virtual ::rtl::OUString SAL_CALL getScheme() + throw (css::uno::RuntimeException) + { return base_.getScheme(); } + + virtual ::rtl::OUString SAL_CALL getSchemeSpecificPart() + throw (css::uno::RuntimeException) + { return base_.getSchemeSpecificPart(); } + + virtual ::sal_Bool SAL_CALL isHierarchical() + throw (css::uno::RuntimeException) + { return base_.isHierarchical(); } + + virtual ::sal_Bool SAL_CALL hasAuthority() + throw (css::uno::RuntimeException) + { return base_.hasAuthority(); } + + virtual ::rtl::OUString SAL_CALL getAuthority() + throw (css::uno::RuntimeException) + { return base_.getAuthority(); } + + virtual ::rtl::OUString SAL_CALL getPath() + throw (css::uno::RuntimeException) + { return base_.getPath(); } + + virtual ::sal_Bool SAL_CALL hasRelativePath() + throw (css::uno::RuntimeException) + { return base_.hasRelativePath(); } + + virtual ::sal_Int32 SAL_CALL getPathSegmentCount() + throw (css::uno::RuntimeException) + { return base_.getPathSegmentCount(); } + + virtual ::rtl::OUString SAL_CALL getPathSegment(sal_Int32 index) + throw (css::uno::RuntimeException) + { return base_.getPathSegment(index); } + + virtual ::sal_Bool SAL_CALL hasQuery() throw (css::uno::RuntimeException) + { return base_.hasQuery(); } + + virtual ::rtl::OUString SAL_CALL getQuery() + throw (css::uno::RuntimeException) + { return base_.getQuery(); } + + virtual ::sal_Bool SAL_CALL hasFragment() throw (css::uno::RuntimeException) + { return base_.hasFragment(); } + + virtual ::rtl::OUString SAL_CALL getFragment() + throw (css::uno::RuntimeException) + { return base_.getFragment(); } + + virtual void SAL_CALL setFragment(::rtl::OUString const & fragment) + throw (css::uno::RuntimeException) + { base_.setFragment(fragment); } + + virtual void SAL_CALL clearFragment() throw (css::uno::RuntimeException) + { base_.clearFragment(); } + + virtual ::rtl::OUString SAL_CALL expand( + css::uno::Reference< css::util::XMacroExpander > const & expander) + throw (css::lang::IllegalArgumentException, css::uno::RuntimeException); + +private: + UrlReference(UrlReference &); // not defined + void operator =(UrlReference); // not defined + + virtual ~UrlReference() {} + + stoc::uriproc::UriReference base_; +}; + +::rtl::OUString UrlReference::expand( + css::uno::Reference< css::util::XMacroExpander > const & expander) + throw (css::lang::IllegalArgumentException, css::uno::RuntimeException) +{ + OSL_ASSERT(expander.is()); + return expander->expandMacros( + ::rtl::Uri::decode( + getPath(), ::rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8)); +} + +class Parser: public ::cppu::WeakImplHelper2< + css::lang::XServiceInfo, css::uri::XUriSchemeParser > +{ +public: + Parser() {} + + virtual ::rtl::OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException); + + virtual ::sal_Bool SAL_CALL supportsService( + ::rtl::OUString const & serviceName) + throw (css::uno::RuntimeException); + + virtual css::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames() throw (css::uno::RuntimeException); + + virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL + parse( + ::rtl::OUString const & scheme, + ::rtl::OUString const & schemeSpecificPart) + throw (css::uno::RuntimeException); + +private: + Parser(Parser &); // not defined + void operator =(Parser); // not defined + + virtual ~Parser() {} +}; + +::rtl::OUString Parser::getImplementationName() + throw (css::uno::RuntimeException) +{ + return ::stoc_services::UriSchemeParser_vndDOTsunDOTstarDOTexpand:: + getImplementationName(); +} + +::sal_Bool Parser::supportsService(::rtl::OUString const & serviceName) + throw (css::uno::RuntimeException) +{ + return ::stoc::uriproc::supportsService( + getSupportedServiceNames(), serviceName); +} + +css::uno::Sequence< ::rtl::OUString > Parser::getSupportedServiceNames() + throw (css::uno::RuntimeException) +{ + return ::stoc_services::UriSchemeParser_vndDOTsunDOTstarDOTexpand:: + getSupportedServiceNames(); +} + +css::uno::Reference< css::uri::XUriReference > Parser::parse( + ::rtl::OUString const & scheme, ::rtl::OUString const & schemeSpecificPart) + throw (css::uno::RuntimeException) +{ + if (!parseSchemeSpecificPart(schemeSpecificPart)) { + return css::uno::Reference< css::uri::XUriReference >(); + } + try { + return new UrlReference(scheme, schemeSpecificPart); + } catch (::std::bad_alloc &) { + throw css::uno::RuntimeException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("std::bad_alloc")), + css::uno::Reference< css::uno::XInterface >()); + } +} + +} + +namespace stoc_services { namespace UriSchemeParser_vndDOTsunDOTstarDOTexpand { + +css::uno::Reference< css::uno::XInterface > create( + css::uno::Reference< css::uno::XComponentContext > const &) + SAL_THROW((css::uno::Exception)) +{ + //TODO: single instance + try { + return static_cast< ::cppu::OWeakObject * >(new Parser); + } catch (::std::bad_alloc &) { + throw css::uno::RuntimeException( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("std::bad_alloc")), + css::uno::Reference< css::uno::XInterface >()); + } +} + +::rtl::OUString getImplementationName() { + return ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.uri.UriSchemeParser_vndDOTsunDOTstarDOTexpand")); +} + +css::uno::Sequence< ::rtl::OUString > getSupportedServiceNames() { + css::uno::Sequence< ::rtl::OUString > s(1); + s[0] = ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.uri.UriSchemeParser_vndDOTsunDOTstarDOTexpand")); + return s; +} + +} } diff --git a/stoc/source/uriproc/UriSchemeParser_vndDOTsunDOTstarDOTexpand.hxx b/stoc/source/uriproc/UriSchemeParser_vndDOTsunDOTstarDOTexpand.hxx new file mode 100644 index 000000000000..2008b7ba82e3 --- /dev/null +++ b/stoc/source/uriproc/UriSchemeParser_vndDOTsunDOTstarDOTexpand.hxx @@ -0,0 +1,62 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef \ + INCLUDED_STOC_SOURCE_URIPROC_URISCHEMEPARSER_VNDDOTSUNDOTSTARDOTEXPAND_HXX +#define \ + INCLUDED_STOC_SOURCE_URIPROC_URISCHEMEPARSER_VNDDOTSUNDOTSTARDOTEXPAND_HXX + +#include "sal/config.h" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "sal/types.h" + +namespace com { namespace sun { namespace star { namespace uno { + class XComponentContext; + class XInterface; +} } } } +namespace rtl { class OUString; } + +namespace stoc { namespace uriproc { + +namespace UriSchemeParser_vndDOTsunDOTstarDOTexpand { + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > + SAL_CALL create( + ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > const &) + SAL_THROW((::com::sun::star::uno::Exception)); + + ::rtl::OUString SAL_CALL getImplementationName(); + + ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedServiceNames(); +} + +} } + +#endif diff --git a/stoc/source/uriproc/UriSchemeParser_vndDOTsunDOTstarDOTscript.cxx b/stoc/source/uriproc/UriSchemeParser_vndDOTsunDOTstarDOTscript.cxx new file mode 100644 index 000000000000..512f18a114ab --- /dev/null +++ b/stoc/source/uriproc/UriSchemeParser_vndDOTsunDOTstarDOTscript.cxx @@ -0,0 +1,485 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include "stocservices.hxx" + +#include "UriReference.hxx" +#include "supportsService.hxx" + +#include "com/sun/star/lang/IllegalArgumentException.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/uri/XUriReference.hpp" +#include "com/sun/star/uri/XUriSchemeParser.hpp" +#include "com/sun/star/uri/XVndSunStarScriptUrlReference.hpp" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/implbase2.hxx" +#include "cppuhelper/weak.hxx" +#include "osl/mutex.hxx" +#include "rtl/uri.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.hxx" +#include "sal/types.h" + +#include <new> + +namespace css = com::sun::star; + +namespace { + +int getHexWeight(sal_Unicode c) { + return c >= '0' && c <= '9' ? static_cast< int >(c - '0') + : c >= 'A' && c <= 'F' ? static_cast< int >(c - 'A' + 10) + : c >= 'a' && c <= 'f' ? static_cast< int >(c - 'a' + 10) + : -1; +} + +int parseEscaped(rtl::OUString const & part, sal_Int32 * index) { + if (part.getLength() - *index < 3 || part[*index] != '%') { + return -1; + } + int n1 = getHexWeight(part[*index + 1]); + int n2 = getHexWeight(part[*index + 2]); + if (n1 < 0 || n2 < 0) { + return -1; + } + *index += 3; + return (n1 << 4) | n2; +} + +rtl::OUString parsePart( + rtl::OUString const & part, bool namePart, sal_Int32 * index) +{ + rtl::OUStringBuffer buf; + while (*index < part.getLength()) { + sal_Unicode c = part[*index]; + if (namePart ? c == '?' : c == '&' || c == '=') { + break; + } else if (c == '%') { + sal_Int32 i = *index; + int n = parseEscaped(part, &i); + if (n >= 0 && n <= 0x7F) { + buf.append(static_cast< sal_Unicode >(n)); + } else if (n >= 0xC0 && n <= 0xFC) { + sal_Int32 encoded; + int shift; + sal_Int32 min; + if (n <= 0xDF) { + encoded = (n & 0x1F) << 6; + shift = 0; + min = 0x80; + } else if (n <= 0xEF) { + encoded = (n & 0x0F) << 12; + shift = 6; + min = 0x800; + } else if (n <= 0xF7) { + encoded = (n & 0x07) << 18; + shift = 12; + min = 0x10000; + } else if (n <= 0xFB) { + encoded = (n & 0x03) << 24; + shift = 18; + min = 0x200000; + } else { + encoded = 0; + shift = 24; + min = 0x4000000; + } + bool utf8 = true; + for (; shift >= 0; shift -= 6) { + n = parseEscaped(part, &i); + if (n < 0x80 || n > 0xBF) { + utf8 = false; + break; + } + encoded |= (n & 0x3F) << shift; + } + if (!utf8 || encoded < min + || (encoded >= 0xD800 && encoded <= 0xDFFF) + || encoded > 0x10FFFF) + { + break; + } + if (encoded <= 0xFFFF) { + buf.append(static_cast< sal_Unicode >(encoded)); + } else { + buf.append(static_cast< sal_Unicode >( + (encoded >> 10) | 0xD800)); + buf.append(static_cast< sal_Unicode >( + (encoded & 0x3FF) | 0xDC00)); + } + } else { + break; + } + *index = i; + } else { + buf.append(c); + ++*index; + } + } + return buf.makeStringAndClear(); +} + +namespace +{ + static rtl::OUString encodeNameOrParamFragment( rtl::OUString const & fragment ) + { + static sal_Bool const aCharClass[] = + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* NameOrParamFragment */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* !"#$%&'()*+,-./*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, /*0123456789:;<=>?*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*@ABCDEFGHIJKLMNO*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, /*PQRSTUVWXYZ[\]^_*/ + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*`abcdefghijklmno*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 /*pqrstuvwxyz{|}~ */ + }; + + return rtl::Uri::encode( + fragment, + aCharClass, + rtl_UriEncodeIgnoreEscapes, + RTL_TEXTENCODING_UTF8 + ); + } +} + +bool parseSchemeSpecificPart(rtl::OUString const & part) { + sal_Int32 len = part.getLength(); + sal_Int32 i = 0; + if (parsePart(part, true, &i).getLength() == 0 || part[0] == '/') { + return false; + } + if (i == len) { + return true; + } + for (;;) { + ++i; // skip '?' or '&' + if (parsePart(part, false, &i).getLength() == 0 || i == len + || part[i] != '=') + { + return false; + } + ++i; + parsePart(part, false, &i); + if (i == len) { + return true; + } + if (part[i] != '&') { + return false; + } + } +} + +class UrlReference: + public cppu::WeakImplHelper1< css::uri::XVndSunStarScriptUrlReference > +{ +public: + UrlReference(rtl::OUString const & scheme, rtl::OUString const & path): + m_base( + scheme, false, false, rtl::OUString(), path, false, rtl::OUString()) + {} + + virtual rtl::OUString SAL_CALL getUriReference() + throw (com::sun::star::uno::RuntimeException) + { return m_base.getUriReference(); } + + virtual sal_Bool SAL_CALL isAbsolute() + throw (com::sun::star::uno::RuntimeException) + { return m_base.isAbsolute(); } + + virtual rtl::OUString SAL_CALL getScheme() + throw (com::sun::star::uno::RuntimeException) + { return m_base.getScheme(); } + + virtual rtl::OUString SAL_CALL getSchemeSpecificPart() + throw (com::sun::star::uno::RuntimeException) + { return m_base.getSchemeSpecificPart(); } + + virtual sal_Bool SAL_CALL isHierarchical() + throw (com::sun::star::uno::RuntimeException) + { return m_base.isHierarchical(); } + + virtual sal_Bool SAL_CALL hasAuthority() + throw (com::sun::star::uno::RuntimeException) + { return m_base.hasAuthority(); } + + virtual rtl::OUString SAL_CALL getAuthority() + throw (com::sun::star::uno::RuntimeException) + { return m_base.getAuthority(); } + + virtual rtl::OUString SAL_CALL getPath() + throw (com::sun::star::uno::RuntimeException) + { return m_base.getPath(); } + + virtual sal_Bool SAL_CALL hasRelativePath() + throw (com::sun::star::uno::RuntimeException) + { return m_base.hasRelativePath(); } + + virtual sal_Int32 SAL_CALL getPathSegmentCount() + throw (com::sun::star::uno::RuntimeException) + { return m_base.getPathSegmentCount(); } + + virtual rtl::OUString SAL_CALL getPathSegment(sal_Int32 index) + throw (com::sun::star::uno::RuntimeException) + { return m_base.getPathSegment(index); } + + virtual sal_Bool SAL_CALL hasQuery() + throw (com::sun::star::uno::RuntimeException) + { return m_base.hasQuery(); } + + virtual rtl::OUString SAL_CALL getQuery() + throw (com::sun::star::uno::RuntimeException) + { return m_base.getQuery(); } + + virtual sal_Bool SAL_CALL hasFragment() + throw (com::sun::star::uno::RuntimeException) + { return m_base.hasFragment(); } + + virtual rtl::OUString SAL_CALL getFragment() + throw (com::sun::star::uno::RuntimeException) + { return m_base.getFragment(); } + + virtual void SAL_CALL setFragment(rtl::OUString const & fragment) + throw (com::sun::star::uno::RuntimeException) + { m_base.setFragment(fragment); } + + virtual void SAL_CALL clearFragment() + throw (com::sun::star::uno::RuntimeException) + { m_base.clearFragment(); } + + virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException); + + virtual void SAL_CALL setName(rtl::OUString const & name) + throw (css::uno::RuntimeException, css::lang::IllegalArgumentException); + + virtual sal_Bool SAL_CALL hasParameter(rtl::OUString const & key) + throw (css::uno::RuntimeException); + + virtual rtl::OUString SAL_CALL getParameter(rtl::OUString const & key) + throw (css::uno::RuntimeException); + + virtual void SAL_CALL setParameter(rtl::OUString const & key, rtl::OUString const & value) + throw (css::uno::RuntimeException, css::lang::IllegalArgumentException); + +private: + UrlReference(UrlReference &); // not implemented + void operator =(UrlReference); // not implemented + + virtual ~UrlReference() {} + + sal_Int32 findParameter(rtl::OUString const & key); + + stoc::uriproc::UriReference m_base; +}; + +rtl::OUString UrlReference::getName() throw (css::uno::RuntimeException) { + osl::MutexGuard g(m_base.m_mutex); + sal_Int32 i = 0; + return parsePart(m_base.m_path, true, &i); +} + +void SAL_CALL UrlReference::setName(rtl::OUString const & name) throw (css::uno::RuntimeException, css::lang::IllegalArgumentException) +{ + if (name.getLength() == 0) + throw css::lang::IllegalArgumentException( + ::rtl::OUString(), *this, 1); + + osl::MutexGuard g(m_base.m_mutex); + sal_Int32 i = 0; + parsePart(m_base.m_path, true, &i); + + rtl::OUStringBuffer newPath; + newPath.append(encodeNameOrParamFragment(name)); + newPath.append(m_base.m_path.copy(i)); + m_base.m_path = newPath.makeStringAndClear(); +} + +sal_Bool UrlReference::hasParameter(rtl::OUString const & key) + throw (css::uno::RuntimeException) +{ + osl::MutexGuard g(m_base.m_mutex); + return findParameter(key) >= 0; +} + +rtl::OUString UrlReference::getParameter(rtl::OUString const & key) + throw (css::uno::RuntimeException) +{ + osl::MutexGuard g(m_base.m_mutex); + sal_Int32 i = findParameter(key); + return i >= 0 ? parsePart(m_base.m_path, false, &i) : rtl::OUString(); +} + +void UrlReference::setParameter(rtl::OUString const & key, rtl::OUString const & value) + throw (css::uno::RuntimeException, css::lang::IllegalArgumentException) +{ + if (key.getLength() == 0) + throw css::lang::IllegalArgumentException( + ::rtl::OUString(), *this, 1); + + osl::MutexGuard g(m_base.m_mutex); + sal_Int32 i = findParameter(key); + bool bExistent = ( i>=0 ); + if (!bExistent) { + i = m_base.m_path.getLength(); + } + + rtl::OUStringBuffer newPath; + newPath.append(m_base.m_path.copy(0, i)); + if (!bExistent) { + newPath.append(sal_Unicode(m_base.m_path.indexOf('?') < 0 ? '?' : '&')); + newPath.append(encodeNameOrParamFragment(key)); + newPath.append(sal_Unicode('=')); + } + newPath.append(encodeNameOrParamFragment(value)); + if (bExistent) { + /*oldValue = */ + parsePart(m_base.m_path, false, &i); // skip key + newPath.append(m_base.m_path.copy(i)); + } + + m_base.m_path = newPath.makeStringAndClear(); +} + +sal_Int32 UrlReference::findParameter(rtl::OUString const & key) { + sal_Int32 i = 0; + parsePart(m_base.m_path, true, &i); // skip name + for (;;) { + if (i == m_base.m_path.getLength()) { + return -1; + } + ++i; // skip '?' or '&' + rtl::OUString k = parsePart(m_base.m_path, false, &i); + ++i; // skip '=' + if (k == key) { + return i; + } + parsePart(m_base.m_path, false, &i); // skip value + } +} + +class Parser: public cppu::WeakImplHelper2< + css::lang::XServiceInfo, css::uri::XUriSchemeParser > +{ +public: + Parser() {} + + virtual rtl::OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & serviceName) + throw (css::uno::RuntimeException); + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames() throw (css::uno::RuntimeException); + + virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL + parse( + rtl::OUString const & scheme, rtl::OUString const & schemeSpecificPart) + throw (css::uno::RuntimeException); + +private: + Parser(Parser &); // not implemented + void operator =(Parser); // not implemented + + virtual ~Parser() {} +}; + +rtl::OUString Parser::getImplementationName() + throw (css::uno::RuntimeException) +{ + return stoc_services::UriSchemeParser_vndDOTsunDOTstarDOTscript:: + getImplementationName(); +} + +sal_Bool Parser::supportsService(rtl::OUString const & serviceName) + throw (css::uno::RuntimeException) +{ + return stoc::uriproc::supportsService( + getSupportedServiceNames(), serviceName); +} + +css::uno::Sequence< rtl::OUString > Parser::getSupportedServiceNames() + throw (css::uno::RuntimeException) +{ + return stoc_services::UriSchemeParser_vndDOTsunDOTstarDOTscript:: + getSupportedServiceNames(); +} + +css::uno::Reference< css::uri::XUriReference > +Parser::parse( + rtl::OUString const & scheme, rtl::OUString const & schemeSpecificPart) + throw (css::uno::RuntimeException) +{ + if (!parseSchemeSpecificPart(schemeSpecificPart)) { + return 0; + } + try { + return new UrlReference(scheme, schemeSpecificPart); + } catch (std::bad_alloc &) { + throw css::uno::RuntimeException( + rtl::OUString::createFromAscii("std::bad_alloc"), 0); + } +} + +} + +namespace stoc_services { +namespace UriSchemeParser_vndDOTsunDOTstarDOTscript { + +css::uno::Reference< css::uno::XInterface > create( + css::uno::Reference< css::uno::XComponentContext > const &) + SAL_THROW((css::uno::Exception)) +{ + //TODO: single instance + try { + return static_cast< cppu::OWeakObject * >(new Parser); + } catch (std::bad_alloc &) { + throw css::uno::RuntimeException( + rtl::OUString::createFromAscii("std::bad_alloc"), 0); + } +} + +rtl::OUString getImplementationName() { + return rtl::OUString::createFromAscii( + "com.sun.star.comp.uri.UriSchemeParser_vndDOTsunDOTstarDOTscript"); +} + +css::uno::Sequence< rtl::OUString > getSupportedServiceNames() { + css::uno::Sequence< rtl::OUString > s(1); + s[0] = rtl::OUString::createFromAscii( + "com.sun.star.uri.UriSchemeParser_vndDOTsunDOTstarDOTscript"); + return s; +} + +} } diff --git a/stoc/source/uriproc/UriSchemeParser_vndDOTsunDOTstarDOTscript.hxx b/stoc/source/uriproc/UriSchemeParser_vndDOTsunDOTstarDOTscript.hxx new file mode 100644 index 000000000000..00c39ef0e0be --- /dev/null +++ b/stoc/source/uriproc/UriSchemeParser_vndDOTsunDOTstarDOTscript.hxx @@ -0,0 +1,61 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef \ + INCLUDED_stoc_source_uriproc_UriSchemeParser_vndDOTsunDOTstarDOTscript_hxx +#define \ + INCLUDED_stoc_source_uriproc_UriSchemeParser_vndDOTsunDOTstarDOTscript_hxx + +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "sal/types.h" + +namespace com { namespace sun { namespace star { namespace uno { + class XComponentContext; + class XInterface; +} } } } +namespace rtl { class OUString; } + +namespace stoc { namespace uriproc { + +namespace UriSchemeParser_vndDOTsunDOTstarDOTscript { + com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL + create( + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + const &) + SAL_THROW((com::sun::star::uno::Exception)); + + rtl::OUString SAL_CALL getImplementationName(); + + com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames(); +} + +} } + +#endif diff --git a/stoc/source/uriproc/VndSunStarPkgUrlReferenceFactory.cxx b/stoc/source/uriproc/VndSunStarPkgUrlReferenceFactory.cxx new file mode 100644 index 000000000000..0422bad6a770 --- /dev/null +++ b/stoc/source/uriproc/VndSunStarPkgUrlReferenceFactory.cxx @@ -0,0 +1,167 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include "stocservices.hxx" + +#include "supportsService.hxx" + +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "com/sun/star/uri/UriReferenceFactory.hpp" +#include "com/sun/star/uri/XUriReference.hpp" +#include "com/sun/star/uri/XUriReferenceFactory.hpp" +#include "com/sun/star/uri/XVndSunStarPkgUrlReferenceFactory.hpp" +#include "cppuhelper/implbase2.hxx" +#include "cppuhelper/weak.hxx" +#include "rtl/string.h" +#include "rtl/textenc.h" +#include "rtl/uri.h" +#include "rtl/uri.hxx" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.hxx" +#include "sal/types.h" + +#include <new> + +namespace css = com::sun::star; + +namespace { + +class Factory: public cppu::WeakImplHelper2< + css::lang::XServiceInfo, css::uri::XVndSunStarPkgUrlReferenceFactory > +{ +public: + explicit Factory( + css::uno::Reference< css::uno::XComponentContext > const & context): + m_context(context) {} + + virtual rtl::OUString SAL_CALL getImplementationName() + throw (css::uno::RuntimeException); + + virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & serviceName) + throw (css::uno::RuntimeException); + + virtual css::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames() throw (css::uno::RuntimeException); + + virtual css::uno::Reference< css::uri::XUriReference > SAL_CALL + createVndSunStarPkgUrlReference( + css::uno::Reference< css::uri::XUriReference > const & authority) + throw (css::uno::RuntimeException); + +private: + Factory(Factory &); // not implemented + void operator =(Factory); // not implemented + + virtual ~Factory() {} + + css::uno::Reference< css::uno::XComponentContext > m_context; +}; + +rtl::OUString Factory::getImplementationName() + throw (css::uno::RuntimeException) +{ + return + stoc_services::VndSunStarPkgUrlReferenceFactory:: + getImplementationName(); +} + +sal_Bool Factory::supportsService(rtl::OUString const & serviceName) + throw (css::uno::RuntimeException) +{ + return stoc::uriproc::supportsService( + getSupportedServiceNames(), serviceName); +} + +css::uno::Sequence< rtl::OUString > Factory::getSupportedServiceNames() + throw (css::uno::RuntimeException) +{ + return stoc_services::VndSunStarPkgUrlReferenceFactory:: + getSupportedServiceNames(); +} + +css::uno::Reference< css::uri::XUriReference > +Factory::createVndSunStarPkgUrlReference( + css::uno::Reference< css::uri::XUriReference > const & authority) + throw (css::uno::RuntimeException) +{ + OSL_ASSERT(authority.is()); + if (authority->isAbsolute() && !authority->hasFragment()) { + rtl::OUStringBuffer buf; + buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.pkg://")); + buf.append( + rtl::Uri::encode( + authority->getUriReference(), rtl_UriCharClassRegName, + rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8)); + css::uno::Reference< css::uri::XUriReference > uriRef( + css::uri::UriReferenceFactory::create(m_context)->parse( + buf.makeStringAndClear())); + OSL_ASSERT(uriRef.is()); + return uriRef; + } else { + return css::uno::Reference< css::uri::XUriReference >(); + } +} + +} + +namespace stoc_services { namespace VndSunStarPkgUrlReferenceFactory +{ + +css::uno::Reference< css::uno::XInterface > create( + css::uno::Reference< css::uno::XComponentContext > const & context) + SAL_THROW((css::uno::Exception)) +{ + try { + return static_cast< cppu::OWeakObject * >(new Factory(context)); + } catch (std::bad_alloc &) { + throw css::uno::RuntimeException( + rtl::OUString::createFromAscii("std::bad_alloc"), 0); + } +} + +rtl::OUString getImplementationName() { + return rtl::OUString::createFromAscii( + "com.sun.star.comp.uri.VndSunStarPkgUrlReferenceFactory"); +} + +css::uno::Sequence< rtl::OUString > getSupportedServiceNames() { + css::uno::Sequence< rtl::OUString > s(1); + s[0] = rtl::OUString::createFromAscii( + "com.sun.star.uri.VndSunStarPkgUrlReferenceFactory"); + return s; +} + +} } diff --git a/stoc/source/uriproc/VndSunStarPkgUrlReferenceFactory.hxx b/stoc/source/uriproc/VndSunStarPkgUrlReferenceFactory.hxx new file mode 100644 index 000000000000..2e869d4e2648 --- /dev/null +++ b/stoc/source/uriproc/VndSunStarPkgUrlReferenceFactory.hxx @@ -0,0 +1,59 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_stoc_source_uriproc_VndSunStarPkgUrlReferenceFactory_hxx +#define INCLUDED_stoc_source_uriproc_VndSunStarPkgUrlReferenceFactory_hxx + +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/Sequence.hxx" +#include "sal/types.h" + +namespace com { namespace sun { namespace star { namespace uno { + class XComponentContext; + class XInterface; +} } } } +namespace rtl { class OUString; } + +namespace stoc { namespace uriproc { + +namespace VndSunStarPkgUrlReferenceFactory { + com::sun::star::uno::Reference< com::sun::star::uno::XInterface > SAL_CALL + create( + com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > + const & context) + SAL_THROW((com::sun::star::uno::Exception)); + + rtl::OUString SAL_CALL getImplementationName(); + + com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL + getSupportedServiceNames(); +} + +} } + +#endif diff --git a/stoc/source/uriproc/makefile.mk b/stoc/source/uriproc/makefile.mk new file mode 100644 index 000000000000..194da2219b6b --- /dev/null +++ b/stoc/source/uriproc/makefile.mk @@ -0,0 +1,53 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. +PRJNAME=stoc +TARGET=uriproc +ENABLE_EXCEPTIONS := TRUE + +# --- openoffice.org.orig/Settings ----------------------------------------------------- + +.INCLUDE: settings.mk +DLLPRE = + +# ------------------------------------------------------------------ + +.INCLUDE : ..$/cppumaker.mk + +SLOFILES = \ + $(SLO)$/ExternalUriReferenceTranslator.obj \ + $(SLO)$/UriReference.obj \ + $(SLO)$/UriReferenceFactory.obj \ + $(SLO)$/UriSchemeParser_vndDOTsunDOTstarDOTexpand.obj \ + $(SLO)$/UriSchemeParser_vndDOTsunDOTstarDOTscript.obj \ + $(SLO)$/VndSunStarPkgUrlReferenceFactory.obj \ + $(SLO)$/supportsService.obj + +# ------------------------------------------------------------------ + +.INCLUDE: target.mk diff --git a/stoc/source/uriproc/supportsService.cxx b/stoc/source/uriproc/supportsService.cxx new file mode 100644 index 000000000000..77b55252bd4d --- /dev/null +++ b/stoc/source/uriproc/supportsService.cxx @@ -0,0 +1,51 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include "supportsService.hxx" + +#include "com/sun/star/uno/Sequence.hxx" +#include "rtl/ustring.hxx" +#include "sal/types.h" + +namespace stoc { namespace uriproc { + +bool supportsService( + com::sun::star::uno::Sequence< rtl::OUString > const & serviceNames, + rtl::OUString const & serviceName) +{ + for (sal_Int32 i = 0; i < serviceNames.getLength(); ++i) { + if (serviceNames[i] == serviceName) { + return true; + } + } + return false; +} + +} } diff --git a/stoc/source/uriproc/supportsService.hxx b/stoc/source/uriproc/supportsService.hxx new file mode 100644 index 000000000000..35b2ed662195 --- /dev/null +++ b/stoc/source/uriproc/supportsService.hxx @@ -0,0 +1,43 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_stoc_source_uriproc_supportsService_hxx +#define INCLUDED_stoc_source_uriproc_supportsService_hxx + +#include "com/sun/star/uno/Sequence.hxx" + +namespace rtl { class OUString; } + +namespace stoc { namespace uriproc { + +bool supportsService( + com::sun::star::uno::Sequence< rtl::OUString > const & serviceNames, + rtl::OUString const & serviceName); + +} } + +#endif |