diff options
Diffstat (limited to 'stoc')
175 files changed, 48082 insertions, 0 deletions
diff --git a/stoc/inc/bootstrapservices.hxx b/stoc/inc/bootstrapservices.hxx new file mode 100644 index 000000000000..56bfda2612f3 --- /dev/null +++ b/stoc/inc/bootstrapservices.hxx @@ -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 <rtl/ustring.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/RuntimeException.hpp> + +namespace com { namespace sun { namespace star { namespace uno { + class XInterface; + class XComponentContext; +} } } } + +namespace stoc_bootstrap +{ + //servicemanager + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL OServiceManager_CreateInstance( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > & xContext ); + ::com::sun::star::uno::Sequence< ::rtl::OUString > smgr_wrapper_getSupportedServiceNames(); + ::rtl::OUString smgr_wrapper_getImplementationName(); + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL OServiceManagerWrapper_CreateInstance( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > & xContext ) + throw (::com::sun::star::uno::Exception); + ::com::sun::star::uno::Sequence< ::rtl::OUString > smgr_getSupportedServiceNames(); + ::rtl::OUString smgr_getImplementationName(); + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL ORegistryServiceManager_CreateInstance( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > & xContext ) + throw(::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + ::com::sun::star::uno::Sequence< ::rtl::OUString > regsmgr_getSupportedServiceNames(); + ::rtl::OUString regsmgr_getImplementationName(); + + //security + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL ac_create( + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const & xComponentContext ) + SAL_THROW( (::com::sun::star::uno::Exception) ); + ::com::sun::star::uno::Sequence< ::rtl::OUString > ac_getSupportedServiceNames() SAL_THROW( () ); + ::rtl::OUString ac_getImplementationName() SAL_THROW( () ); + + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL filepolicy_create( + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const & xComponentContext ) + SAL_THROW( (com::sun::star::uno::Exception) ); + ::com::sun::star::uno::Sequence< rtl::OUString > filepolicy_getSupportedServiceNames() SAL_THROW( () ); + ::rtl::OUString filepolicy_getImplementationName() SAL_THROW( () ); + + //defaultregistry + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL NestedRegistry_CreateInstance( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& ) + throw( ::com::sun::star::uno::Exception); + ::com::sun::star::uno::Sequence< ::rtl::OUString > defreg_getSupportedServiceNames(); + ::rtl::OUString defreg_getImplementationName(); + + //simpleregistry + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL SimpleRegistry_CreateInstance( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& ); + ::com::sun::star::uno::Sequence< ::rtl::OUString > simreg_getSupportedServiceNames(); + ::rtl::OUString simreg_getImplementationName(); + + //implementationregistry + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL ImplementationRegistration_CreateInstance( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& ); // throw(Exception) + ::com::sun::star::uno::Sequence< ::rtl::OUString > impreg_getSupportedServiceNames(); + ::rtl::OUString impreg_getImplementationName(); + + //loader + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL DllComponentLoader_CreateInstance( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& ) + throw(::com::sun::star::uno::Exception); + ::com::sun::star::uno::Sequence< ::rtl::OUString > loader_getSupportedServiceNames(); + ::rtl::OUString loader_getImplementationName(); + + //registry_tdprovider + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL ProviderImpl_create( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& ) + throw(::com::sun::star::uno::Exception); + ::com::sun::star::uno::Sequence< ::rtl::OUString > rdbtdp_getSupportedServiceNames(); + ::rtl::OUString rdbtdp_getImplementationName(); + + //tdmanager + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL ManagerImpl_create( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& ) + SAL_THROW( (::com::sun::star::uno::Exception) ); + ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL tdmgr_getSupportedServiceNames(); + ::rtl::OUString SAL_CALL tdmgr_getImplementationName(); +} // namespace diff --git a/stoc/inc/makefile.mk b/stoc/inc/makefile.mk new file mode 100644 index 000000000000..11c064b3a0a7 --- /dev/null +++ b/stoc/inc/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=inc + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk + +.IF "$(ENABLE_PCH)"!="" +ALLTAR : \ + $(SLO)$/precompiled.pch \ + $(SLO)$/precompiled_ex.pch + +.ENDIF # "$(ENABLE_PCH)"!="" + diff --git a/stoc/inc/pch/precompiled_stoc.cxx b/stoc/inc/pch/precompiled_stoc.cxx new file mode 100644 index 000000000000..309f053446c8 --- /dev/null +++ b/stoc/inc/pch/precompiled_stoc.cxx @@ -0,0 +1,29 @@ +/************************************************************************* + * + * 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" + diff --git a/stoc/inc/pch/precompiled_stoc.hxx b/stoc/inc/pch/precompiled_stoc.hxx new file mode 100644 index 000000000000..965dc87ff23c --- /dev/null +++ b/stoc/inc/pch/precompiled_stoc.hxx @@ -0,0 +1,289 @@ +/************************************************************************* + * + * 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): Generated on 2006-09-01 17:50:03.092339 + +// breaks some builds (e.g. pyuno and i18npool on Mac OS X) +#if 0 +#ifdef PRECOMPILED_HEADERS +//---MARKER--- +#include "sal/alloca.h" +#include "sal/config.h" +#include "sal/main.h" +#include "sal/types.h" + +#include "boost/scoped_array.hpp" + +#include "com/sun/star/beans/IllegalTypeException.hpp" +#include "com/sun/star/beans/MethodConcept.hpp" +#include "com/sun/star/beans/NamedValue.hpp" +#include "com/sun/star/beans/Property.hpp" +#include "com/sun/star/beans/PropertyAttribute.hpp" +#include "com/sun/star/beans/PropertyChangeEvent.hpp" +#include "com/sun/star/beans/PropertyConcept.hpp" +#include "com/sun/star/beans/PropertyState.hpp" +#include "com/sun/star/beans/PropertyValue.hpp" +#include "com/sun/star/beans/PropertyVetoException.hpp" +#include "com/sun/star/beans/UnknownPropertyException.hpp" +#include "com/sun/star/beans/XExactName.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/XPropertyChangeListener.hpp" +#include "com/sun/star/beans/XPropertySet.hpp" +#include "com/sun/star/beans/XPropertySetInfo.hpp" +#include "com/sun/star/beans/XVetoableChangeListener.hpp" +#include "com/sun/star/connection/SocketPermission.hpp" +#include "com/sun/star/container/ContainerEvent.hpp" +#include "com/sun/star/container/ElementExistException.hpp" +#include "com/sun/star/container/NoSuchElementException.hpp" +#include "com/sun/star/container/XContainer.hpp" +#include "com/sun/star/container/XContainerListener.hpp" +#include "com/sun/star/container/XContentEnumerationAccess.hpp" +#include "com/sun/star/container/XElementAccess.hpp" +#include "com/sun/star/container/XEnumeration.hpp" +#include "com/sun/star/container/XEnumerationAccess.hpp" +#include "com/sun/star/container/XHierarchicalNameAccess.hpp" +#include "com/sun/star/container/XIndexAccess.hpp" +#include "com/sun/star/container/XIndexContainer.hpp" +#include "com/sun/star/container/XIndexReplace.hpp" +#include "com/sun/star/container/XNameAccess.hpp" +#include "com/sun/star/container/XNameContainer.hpp" +#include "com/sun/star/container/XNameReplace.hpp" +#include "com/sun/star/container/XSet.hpp" +#include "com/sun/star/io/FilePermission.hpp" +#include "com/sun/star/java/InvalidJavaSettingsException.hpp" +#include "com/sun/star/java/JavaDisabledException.hpp" +#include "com/sun/star/java/JavaInitializationException.hpp" +#include "com/sun/star/java/JavaNotConfiguredException.hpp" +#include "com/sun/star/java/JavaNotFoundException.hpp" +#include "com/sun/star/java/JavaVMCreationFailureException.hpp" +#include "com/sun/star/java/MissingJavaRuntimeException.hpp" +#include "com/sun/star/java/RestartRequiredException.hpp" +#include "com/sun/star/java/XJavaThreadRegister_11.hpp" +#include "com/sun/star/java/XJavaVM.hpp" +#include "com/sun/star/lang/ArrayIndexOutOfBoundsException.hpp" +#include "com/sun/star/lang/DisposedException.hpp" +#include "com/sun/star/lang/EventObject.hpp" +#include "com/sun/star/lang/IllegalAccessException.hpp" +#include "com/sun/star/lang/IllegalArgumentException.hpp" +#include "com/sun/star/lang/IndexOutOfBoundsException.hpp" +#include "com/sun/star/lang/NoSuchMethodException.hpp" +#include "com/sun/star/lang/WrappedTargetException.hpp" +#include "com/sun/star/lang/WrappedTargetRuntimeException.hpp" +#include "com/sun/star/lang/XComponent.hpp" +#include "com/sun/star/lang/XEventListener.hpp" +#include "com/sun/star/lang/XInitialization.hpp" +#include "com/sun/star/lang/XMain.hpp" +#include "com/sun/star/lang/XMultiComponentFactory.hpp" +#include "com/sun/star/lang/XMultiServiceFactory.hpp" +#include "com/sun/star/lang/XServiceInfo.hpp" +#include "com/sun/star/lang/XSingleComponentFactory.hpp" +#include "com/sun/star/lang/XSingleServiceFactory.hpp" +#include "com/sun/star/lang/XTypeProvider.hpp" +#include "com/sun/star/lang/XUnoTunnel.hpp" +#include "com/sun/star/loader/CannotActivateFactoryException.hpp" +#include "com/sun/star/loader/XImplementationLoader.hpp" +#include "com/sun/star/reflection/FieldAccessMode.hpp" +#include "com/sun/star/reflection/InvalidTypeNameException.hpp" +#include "com/sun/star/reflection/InvocationTargetException.hpp" +#include "com/sun/star/reflection/MethodMode.hpp" +#include "com/sun/star/reflection/NoSuchTypeNameException.hpp" +#include "com/sun/star/reflection/ParamInfo.hpp" +#include "com/sun/star/reflection/ParamMode.hpp" +#include "com/sun/star/reflection/TypeDescriptionSearchDepth.hpp" +#include "com/sun/star/reflection/XArrayTypeDescription.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/XIdlArray.hpp" +#include "com/sun/star/reflection/XIdlClass.hpp" +#include "com/sun/star/reflection/XIdlClassProvider.hpp" +#include "com/sun/star/reflection/XIdlField.hpp" +#include "com/sun/star/reflection/XIdlField2.hpp" +#include "com/sun/star/reflection/XIdlMember.hpp" +#include "com/sun/star/reflection/XIdlMethod.hpp" +#include "com/sun/star/reflection/XIdlReflection.hpp" +#include "com/sun/star/reflection/XIndirectTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceAttributeTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp" +#include "com/sun/star/reflection/XInterfaceMemberTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceTypeDescription2.hpp" +#include "com/sun/star/reflection/XMethodParameter.hpp" +#include "com/sun/star/reflection/XModuleTypeDescription.hpp" +#include "com/sun/star/reflection/XParameter.hpp" +#include "com/sun/star/reflection/XPropertyTypeDescription.hpp" +#include "com/sun/star/reflection/XProxyFactory.hpp" +#include "com/sun/star/reflection/XPublished.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/XSingletonTypeDescription.hpp" +#include "com/sun/star/reflection/XSingletonTypeDescription2.hpp" +#include "com/sun/star/reflection/XStructTypeDescription.hpp" +#include "com/sun/star/reflection/XTypeDescription.hpp" +#include "com/sun/star/reflection/XTypeDescriptionEnumeration.hpp" +#include "com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp" +#include "com/sun/star/registry/CannotRegisterImplementationException.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/RegistryValueType.hpp" +#include "com/sun/star/registry/XImplementationRegistration.hpp" +#include "com/sun/star/registry/XRegistryKey.hpp" +#include "com/sun/star/registry/XSimpleRegistry.hpp" +#include "com/sun/star/script/CannotConvertException.hpp" +#include "com/sun/star/script/FailReason.hpp" +#include "com/sun/star/script/InvocationInfo.hpp" +#include "com/sun/star/script/MemberType.hpp" +#include "com/sun/star/script/XInvocation.hpp" +#include "com/sun/star/script/XInvocation2.hpp" +#include "com/sun/star/script/XInvocationAdapterFactory.hpp" +#include "com/sun/star/script/XInvocationAdapterFactory2.hpp" +#include "com/sun/star/script/XTypeConverter.hpp" +#include "com/sun/star/security/AccessControlException.hpp" +#include "com/sun/star/security/AllPermission.hpp" +#include "com/sun/star/security/RuntimePermission.hpp" +#include "com/sun/star/security/XAccessControlContext.hpp" +#include "com/sun/star/security/XAccessController.hpp" +#include "com/sun/star/security/XAction.hpp" +#include "com/sun/star/security/XPolicy.hpp" +#include "com/sun/star/task/XInteractionAbort.hpp" +#include "com/sun/star/task/XInteractionContinuation.hpp" +#include "com/sun/star/task/XInteractionHandler.hpp" +#include "com/sun/star/task/XInteractionRequest.hpp" +#include "com/sun/star/task/XInteractionRetry.hpp" +#include "com/sun/star/uno/Any.h" +#include "com/sun/star/uno/Any.hxx" +#include "com/sun/star/uno/DeploymentException.hpp" +#include "com/sun/star/uno/Exception.hpp" +#include "com/sun/star/uno/Reference.h" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/RuntimeException.hpp" +#include "com/sun/star/uno/SecurityException.hpp" +#include "com/sun/star/uno/Sequence.h" +#include "com/sun/star/uno/Sequence.hxx" +#include "com/sun/star/uno/Type.h" +#include "com/sun/star/uno/Type.hxx" +#include "com/sun/star/uno/TypeClass.hpp" +#include "com/sun/star/uno/Uik.hpp" +#include "com/sun/star/uno/XAdapter.hpp" +#include "com/sun/star/uno/XAggregation.hpp" +#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/uno/XNamingService.hpp" +#include "com/sun/star/uno/XReference.hpp" +#include "com/sun/star/uno/XUnloadingPreference.hpp" +#include "com/sun/star/uri/RelativeUriExcessParentSegments.hpp" +#include "com/sun/star/uri/XExternalUriReferenceTranslator.hpp" +#include "com/sun/star/uri/XUriReference.hpp" +#include "com/sun/star/uri/XUriReferenceFactory.hpp" +#include "com/sun/star/uri/XUriSchemeParser.hpp" +#include "com/sun/star/uri/XVndSunStarPkgUrlReferenceFactory.hpp" +#include "com/sun/star/uri/XVndSunStarScriptUrlReference.hpp" +#include "com/sun/star/util/XMacroExpander.hpp" + +#include "cppu/macros.hxx" +#include "cppu/unotype.hxx" + +#include "cppuhelper/access_control.hxx" +#include "cppuhelper/bootstrap.hxx" +#include "cppuhelper/component_context.hxx" +#include "cppuhelper/exc_hlp.hxx" +#include "cppuhelper/factory.hxx" +#include "cppuhelper/implementationentry.hxx" +#include "cppuhelper/queryinterface.hxx" +#include "cppuhelper/servicefactory.hxx" +#include "cppuhelper/shlib.hxx" +#include "cppuhelper/typeprovider.hxx" +#include "cppuhelper/weak.hxx" +#include "cppuhelper/weakref.hxx" + + + + +#include "jvmfwk/framework.h" + +#include "osl/diagnose.h" +#include "osl/doublecheckedlocking.h" +#include "osl/file.h" +#include "osl/file.hxx" +#include "osl/interlck.h" +#include "osl/module.h" +#include "osl/module.hxx" +#include "osl/mutex.hxx" +#include "osl/process.h" +#include "osl/security.h" +#include "osl/socket.hxx" +#include "osl/thread.h" +#include "osl/thread.hxx" + +#include "registry/refltype.hxx" +#include "registry/registry.hxx" +#include "registry/types.h" +#include "registry/version.h" + +#include "rtl/alloc.h" +#include "rtl/bootstrap.hxx" +#include "rtl/byteseq.hxx" +#include "rtl/process.h" +#include "rtl/strbuf.hxx" +#include "rtl/string.h" +#include "rtl/string.hxx" +#include "rtl/textenc.h" +#include "rtl/unload.h" +#include "rtl/uri.h" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" + +#include "salhelper/simplereferenceobject.hxx" + + +#include "typelib/typeclass.h" +#include "typelib/typedescription.h" +#include "typelib/typedescription.hxx" + +#include "uno/any2.h" +#include "uno/current_context.h" +#include "uno/current_context.hxx" +#include "uno/data.h" +#include "uno/dispatcher.h" +#include "uno/dispatcher.hxx" +#include "uno/environment.h" +#include "uno/environment.hxx" +#include "uno/lbnames.h" +#include "uno/mapping.hxx" +//---MARKER--- +#endif +#endif diff --git a/stoc/inc/stocservices.hxx b/stoc/inc/stocservices.hxx new file mode 100644 index 000000000000..efdd62f9ff43 --- /dev/null +++ b/stoc/inc/stocservices.hxx @@ -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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" + +#include <rtl/ustring.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/RuntimeException.hpp> + +namespace com { namespace sun { namespace star { namespace uno { + class XInterface; + class XComponentContext; +} } } } + +namespace stoc_services +{ + // typeconv + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL TypeConverter_Impl_CreateInstance( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > & ) + throw( ::com::sun::star::uno::RuntimeException ); + ::com::sun::star::uno::Sequence< ::rtl::OUString > tcv_getSupportedServiceNames(); + ::rtl::OUString tcv_getImplementationName(); + + 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(); + } + + 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(); + } + + 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(); + } + + 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(); + } + + 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(); + } +} // namespace diff --git a/stoc/prj/build.lst b/stoc/prj/build.lst new file mode 100644 index 000000000000..1fb7d34eeb32 --- /dev/null +++ b/stoc/prj/build.lst @@ -0,0 +1,25 @@ +tc stoc : rdbmaker cppuhelper cppu jvmaccess sal salhelper jvmfwk NULL +tc stoc usr1 - all tc_mkout NULL +tc stoc\inc nmake - all tc_inc NULL +tc stoc\source\defaultregistry nmake - all tc_defr tc_boot tc_inc NULL +tc stoc\source\implementationregistration nmake - all tc_ireg tc_boot tc_defr tc_inc NULL +tc stoc\source\loader nmake - all tc_loa tc_boot tc_ireg tc_inc NULL +tc stoc\source\bootstrap nmake - all tc_boot tc_inc NULL +tc stoc\source\stocservices nmake - all tc_stserv tc_inc NULL +tc stoc\source\servicemanager nmake - all tc_smgr tc_boot tc_loa tc_inc NULL +tc stoc\source\security nmake - all tc_sec tc_boot tc_loa tc_inc NULL +tc stoc\source\simpleregistry nmake - all tc_sreg tc_boot tc_smgr tc_inc NULL +tc stoc\source\registry_tdprovider nmake - all tc_regtd tc_boot tc_sreg tc_inc NULL +tc stoc\source\tdmanager nmake - all tc_tdmng tc_boot tc_regtd tc_inc NULL +tc stoc\source\corereflection nmake - all tc_corerefl tc_tdmng tc_inc NULL +tc stoc\source\inspect nmake - all tc_inspect tc_corerefl tc_inc NULL +tc stoc\source\invocation nmake - all tc_invocation tc_inspect tc_inc NULL +tc stoc\source\invocation_adapterfactory nmake - all tc_iadapter tc_invocation tc_inc NULL +tc stoc\source\namingservice nmake - all tc_nservice tc_iadapter tc_inc NULL +tc stoc\source\proxy_factory nmake - all tc_proxyfact tc_inc NULL +tc stoc\source\typeconv nmake - all tc_tcv tc_stserv tc_nservice tc_inc NULL +tc stoc\source\javavm nmake - all tc_jvm tc_inc NULL +tc stoc\source\javaloader nmake - all tc_jvload tc_inc NULL +tc stoc\source\uriproc nmake - all tc_uriproc tc_stserv tc_inc NULL +tc stoc\util nmake - all tc_util tc_boot tc_stserv tc_tcv tc_uriproc tc_smgr tc_inc tc_sreg tc_defr tc_ireg tc_regtd tc_tdmng tc_sec NULL +tc stoc\test\uriproc nmake - all tc_test_uriproc tc_util NULL diff --git a/stoc/prj/d.lst b/stoc/prj/d.lst new file mode 100644 index 000000000000..1f01434bf58a --- /dev/null +++ b/stoc/prj/d.lst @@ -0,0 +1,18 @@ +mkdir: %_DEST%\inc%_EXT%\stoc + +..\%__SRC%\bin\*.dll %_DEST%\bin%_EXT%\* +..\%__SRC%\lib\*.so %_DEST%\lib%_EXT%\* +..\%__SRC%\lib\*.dylib %_DEST%\lib%_EXT%\*.dylib +..\%__SRC%\bin\*.rdb %_DEST%\rdb%_EXT%\* + +..\source\module-description.dtd %_DEST%\xml%_EXT%\module-description.dtd +..\source\corereflection\corefl.xml %_DEST%\xml%_EXT%\reflection.uno.xml +..\source\inspect\insp.xml %_DEST%\xml%_EXT%\introspection.uno.xml +..\source\invocation\inv.xml %_DEST%\xml%_EXT%\invocation.uno.xml +..\source\invocation_adapterfactory\invadp.xml %_DEST%\xml%_EXT%\invocadapt.uno.xml +..\source\javavm\jen.xml %_DEST%\xml%_EXT%\javavm.uno.xml +..\source\javaloader\javaloader.xml %_DEST%\xml%_EXT%\javaloader.uno.xml +..\source\namingservice\namingservice.xml %_DEST%\xml%_EXT%\namingservice.uno.xml +..\source\proxy_factory\proxyfac.xml %_DEST%\xml%_EXT%\proxyfac.uno.xml +..\source\bootstrap\bootstrap.xml %_DEST%\xml%_EXT%\bootstrap.uno.xml +..\source\typeconv\stocserv.xml %_DEST%\xml%_EXT%\stocserv.uno.xml 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..c98ee46d8922 --- /dev/null +++ b/stoc/source/bootstrap/services.cxx @@ -0,0 +1,147 @@ +/************************************************************************* + * + * 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; +} +//================================================================================================== +sal_Bool SAL_CALL component_writeInfo( + void * pServiceManager, void * pRegistryKey ) +{ + return component_writeInfoHelper( pServiceManager, pRegistryKey, g_entries ); +} +//================================================================================================== +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..fd77a646f1e5 --- /dev/null +++ b/stoc/source/corereflection/base.hxx @@ -0,0 +1,456 @@ +/************************************************************************* + * + * 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> + +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + + +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..5c201ad52421 --- /dev/null +++ b/stoc/source/corereflection/crefl.cxx @@ -0,0 +1,546 @@ +/************************************************************************* + * + * 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/registry/XRegistryKey.hpp> +#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(); + _xTDMgr.clear(); + _xMgr.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; +} +//================================================================================================== +sal_Bool SAL_CALL component_writeInfo( + void * pServiceManager, void * pRegistryKey ) +{ + if (component_writeInfoHelper( pServiceManager, pRegistryKey, g_entries )) + { + try + { + // register singleton + registry::XRegistryKey * pKey = + reinterpret_cast< registry::XRegistryKey * >( pRegistryKey ); + Reference< registry::XRegistryKey > xKey( + pKey->createKey( + OUSTR(IMPLNAME "/UNO/SINGLETONS/com.sun.star.reflection.theCoreReflection") ) ); + xKey->setStringValue( OUSTR("com.sun.star.reflection.CoreReflection") ); + return sal_True; + } + catch (Exception & exc) + { +#if OSL_DEBUG_LEVEL > 0 + OString cstr( OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_ENSURE( 0, cstr.getStr() ); +#else + (void) exc; // unused +#endif + } + } + return sal_False; +} +//================================================================================================== +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..062c13d981e5 --- /dev/null +++ b/stoc/source/corereflection/lrucache.hxx @@ -0,0 +1,243 @@ +/************************************************************************* + * + * 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 ) +{ + if (_nCachedElements > 0) + { + ::osl::MutexGuard aGuard( _aCacheMutex ); + 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(); + } +#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..b61eb13aa9ee --- /dev/null +++ b/stoc/source/corereflection/makefile.mk @@ -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. +# +#************************************************************************* +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 + 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..df63bfbfaee1 --- /dev/null +++ b/stoc/source/implementationregistration/implreg.cxx @@ -0,0 +1,1930 @@ +/************************************************************************* + * + * 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]; + + xOldKey->closeKey(); + xRootKey->deleteKey(xOldKey->getKeyName()); + } + + OUString oldTarget = searchLinkTargetForImpl(xRootKey, linkName, oldImpl); + if (oldTarget.getLength()) + { + xRootKey->createLink(linkName, oldTarget); + } + } + + if (hasNoImplementations) + { + bClean = sal_True; + hasNoImplementations = sal_False; + xOldKey->closeKey(); + xRootKey->deleteKey(xOldKey->getKeyName()); + } + } + } 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; + xImplKey->closeKey(); + xReg->getRootKey()->deleteKey(xImplKey->getKeyName()); + } + } + + subKeys = xSource->openKeys(); + if (subKeys.getLength() == 0) + { + xSource->closeKey(); + xReg->getRootKey()->deleteKey(xSource->getKeyName()); + } + } else + { + xSource->closeKey(); + xReg->getRootKey()->deleteKey(xSource->getKeyName()); + } +} + +//================================================================================================== +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; + xServiceKey->closeKey(); + xReg->getRootKey()->deleteKey(xServiceKey->getKeyName()); + } + } + + subKeys = xSource->openKeys(); + if (subKeys.getLength() == 0) + { + xSource->closeKey(); + xReg->getRootKey()->deleteKey(xSource->getKeyName()); + } + } else + { + xSource->closeKey(); + xReg->getRootKey()->deleteKey(xSource->getKeyName()); + } +} + +//-------------------------------------------------------------------------------------------------- +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(); + OUString implName; + + if (serviceKeys.getLength()) + { + const Reference < XRegistryKey > * pServiceKeys = serviceKeys.getConstArray(); + + 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); + } + + } + else + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM( "prepareRegistry(): no service names given by component" ) ), + Reference< XInterface > () ); + } + + 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.cxx b/stoc/source/inspect/introspection.cxx new file mode 100644 index 000000000000..5a09c59c5605 --- /dev/null +++ b/stoc/source/inspect/introspection.cxx @@ -0,0 +1,3118 @@ +/************************************************************************* + * + * 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 <com/sun/star/registry/XRegistryKey.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; +} +//================================================================================================== +sal_Bool SAL_CALL component_writeInfo( void *, void * pRegistryKey ) +{ + if (pRegistryKey) + { + try + { + Reference< XRegistryKey > xNewKey( + reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey( + OUString::createFromAscii( "/" IMPLEMENTATION_NAME "/UNO/SERVICES" ) ) ); + + const Sequence< OUString > & rSNL = + stoc_inspect::ImplIntrospection::getSupportedServiceNames_Static(); + const OUString * pArray = rSNL.getConstArray(); + for ( sal_Int32 nPos = rSNL.getLength(); nPos--; ) + xNewKey->createKey( pArray[nPos] ); + + return sal_True; + } + catch (InvalidRegistryException &) + { + OSL_ENSURE( sal_False, "### InvalidRegistryException!" ); + } + } + return sal_False; +} +//================================================================================================== +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..80e87dbf7cab --- /dev/null +++ b/stoc/source/inspect/makefile.mk @@ -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. +# +#************************************************************************* +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 + 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.cxx b/stoc/source/invocation/invocation.cxx new file mode 100644 index 000000000000..74bdc3fe1359 --- /dev/null +++ b/stoc/source/invocation/invocation.cxx @@ -0,0 +1,1268 @@ +/************************************************************************* + * + * 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; +} +//================================================================================================== +sal_Bool SAL_CALL component_writeInfo( + void * pServiceManager, void * pRegistryKey ) +{ + return component_writeInfoHelper( pServiceManager, pRegistryKey, g_entries ); +} +//================================================================================================== +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..c170bf6b614e --- /dev/null +++ b/stoc/source/invocation/makefile.mk @@ -0,0 +1,65 @@ +#************************************************************************* +# +# 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 + + diff --git a/stoc/source/invocation_adapterfactory/iafactory.cxx b/stoc/source/invocation_adapterfactory/iafactory.cxx new file mode 100644 index 000000000000..2fda1819f891 --- /dev/null +++ b/stoc/source/invocation_adapterfactory/iafactory.cxx @@ -0,0 +1,1033 @@ +/************************************************************************* + * + * 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; +} + +//============================================================================== +sal_Bool SAL_CALL component_writeInfo( + void * pServiceManager, void * pRegistryKey ) +{ + return ::cppu::component_writeInfoHelper( + pServiceManager, pRegistryKey, g_entries ); +} + +//============================================================================== +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/makefile.mk b/stoc/source/invocation_adapterfactory/makefile.mk new file mode 100644 index 000000000000..66568af039e7 --- /dev/null +++ b/stoc/source/invocation_adapterfactory/makefile.mk @@ -0,0 +1,65 @@ +#************************************************************************* +# +# 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 diff --git a/stoc/source/javaloader/javaloader.cxx b/stoc/source/javaloader/javaloader.cxx new file mode 100644 index 000000000000..566612cb2f00 --- /dev/null +++ b/stoc/source/javaloader/javaloader.cxx @@ -0,0 +1,486 @@ +/************************************************************************* + * + * 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; +} +//================================================================================================== +sal_Bool SAL_CALL component_writeInfo( + void * pServiceManager, void * pRegistryKey ) +{ + return component_writeInfoHelper( pServiceManager, pRegistryKey, g_entries ); +} +//================================================================================================== +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..60eea6a23457 --- /dev/null +++ b/stoc/source/javaloader/makefile.mk @@ -0,0 +1,72 @@ +#************************************************************************* +# +# 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 + 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.cxx b/stoc/source/javavm/javavm.cxx new file mode 100644 index 000000000000..ad72a64a811c --- /dev/null +++ b/stoc/source/javavm/javavm.cxx @@ -0,0 +1,1809 @@ +/************************************************************************* + * + * 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")); +} + +rtl::OUString serviceGetServiceName() +{ + return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.java.JavaVirtualMachine")); +} + +css::uno::Sequence< rtl::OUString > serviceGetSupportedServiceNames() +{ + rtl::OUString aServiceName = serviceGetServiceName(); + 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" sal_Bool SAL_CALL component_writeInfo(void * pServiceManager, + void * pRegistryKey) +{ + if (cppu::component_writeInfoHelper(pServiceManager, pRegistryKey, + aServiceImplementation)) + { + try + { + css::uno::Reference< css::registry::XRegistryKey >( + reinterpret_cast< css::registry::XRegistryKey * >( + pRegistryKey)-> + createKey( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.stoc.JavaVirtualMachine" + "/UNO/SINGLETONS/" + "com.sun.star.java.theJavaVirtualMachine"))))-> + setStringValue(serviceGetServiceName()); + return true; + } + catch (css::uno::Exception &) + { + OSL_ENSURE(false, "com.sun.star.uno.Exception caught"); + } + } + return false; +} + +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..96908d10d1a1 --- /dev/null +++ b/stoc/source/javavm/makefile.mk @@ -0,0 +1,87 @@ +#************************************************************************* +# +# 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 + 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..424180e114a1 --- /dev/null +++ b/stoc/source/namingservice/makefile.mk @@ -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. +# +#************************************************************************* +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 + diff --git a/stoc/source/namingservice/namingservice.cxx b/stoc/source/namingservice/namingservice.cxx new file mode 100644 index 000000000000..26ced6e8e973 --- /dev/null +++ b/stoc/source/namingservice/namingservice.cxx @@ -0,0 +1,252 @@ +/************************************************************************* + * + * 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; +} +//================================================================================================== +sal_Bool SAL_CALL component_writeInfo( + void * pServiceManager, void * pRegistryKey ) +{ + return component_writeInfoHelper( pServiceManager, pRegistryKey, g_entries ); +} +//================================================================================================== +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..b38dac146ae1 --- /dev/null +++ b/stoc/source/proxy_factory/makefile.mk @@ -0,0 +1,65 @@ +#************************************************************************* +# +# 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 diff --git a/stoc/source/proxy_factory/proxyfac.cxx b/stoc/source/proxy_factory/proxyfac.cxx new file mode 100644 index 000000000000..76d5edfb536d --- /dev/null +++ b/stoc/source/proxy_factory/proxyfac.cxx @@ -0,0 +1,544 @@ +/************************************************************************* + * + * 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; +} + +sal_Bool SAL_CALL component_writeInfo( + void * pServiceManager, void * pRegistryKey ) +{ + return ::cppu::component_writeInfoHelper( + pServiceManager, pRegistryKey, g_entries ); +} + +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..1d62657beba9 --- /dev/null +++ b/stoc/source/registry_tdprovider/tdprovider.cxx @@ -0,0 +1,632 @@ +/************************************************************************* + * + * 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 + 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) +{ + try + { + return getByHierarchicalName( name ).hasValue(); + } + catch (container::NoSuchElementException &) + { + return false; + } +} + +//______________________________________________________________________________ +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 SAL_CALL ProviderImpl::getByHierarchicalName( const OUString & rName ) + throw(::com::sun::star::uno::RuntimeException, com::sun::star::container::NoSuchElementException) +{ + 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. + } + } + + 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) +{ + try + { + return getByHierarchicalName( rName ).hasValue(); + } + catch (NoSuchElementException &) + { + } + return sal_False; +} + +// 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..e9eb46ac6344 --- /dev/null +++ b/stoc/source/security/file_policy.cxx @@ -0,0 +1,604 @@ +/************************************************************************* + * + * 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_semi = 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..510e7b466d83 --- /dev/null +++ b/stoc/source/simpleregistry/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 = simplereg +ENABLE_EXCEPTIONS=TRUE +BOOTSTRAP_SERVICE=TRUE +UNOUCROUT=$(OUT)$/inc$/bootstrap + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# ------------------------------------------------------------------ + +SLOFILES= \ + $(SLO)$/simpleregistry.obj + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk diff --git a/stoc/source/simpleregistry/simpleregistry.cxx b/stoc/source/simpleregistry/simpleregistry.cxx new file mode 100644 index 000000000000..4ae9875bdab1 --- /dev/null +++ b/stoc/source/simpleregistry/simpleregistry.cxx @@ -0,0 +1,1306 @@ +/************************************************************************* + * + * 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/alloc.h> +#ifndef _RTL_USTRBUF_H_ +#include <rtl/ustrbuf.hxx> +#endif +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/weak.hxx> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase2.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/XSingleServiceFactory.hpp> + +using namespace com::sun::star::uno; +using namespace com::sun::star::registry; +using namespace com::sun::star::lang; +using namespace cppu; +using namespace osl; +using namespace rtl; + +#define SERVICENAME "com.sun.star.registry.SimpleRegistry" +#define IMPLNAME "com.sun.star.comp.stoc.SimpleRegistry" + +extern rtl_StandardModuleCount g_moduleCount; + +namespace stoc_bootstrap +{ +Sequence< OUString > simreg_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 simreg_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_simreg { + +//************************************************************************* +// class RegistryKeyImpl the implenetation of interface XRegistryKey +//************************************************************************* +class RegistryKeyImpl; + +//************************************************************************* +// SimpleRegistryImpl +//************************************************************************* +class SimpleRegistryImpl : public WeakImplHelper2< XSimpleRegistry, XServiceInfo > +{ +public: + SimpleRegistryImpl( const Registry& rRegistry ); + + ~SimpleRegistryImpl(); + + // 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); + + // 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); + + friend class RegistryKeyImpl; +protected: + Mutex m_mutex; + OUString m_url; + Registry m_registry; +}; + + +class RegistryKeyImpl : public WeakImplHelper1< XRegistryKey > +{ +public: + RegistryKeyImpl( const RegistryKey& rKey, SimpleRegistryImpl* pRegistry ); + + RegistryKeyImpl( const OUString& rKeyName, SimpleRegistryImpl* pRegistry ); + + ~RegistryKeyImpl(); + + // 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: + OUString m_name; + RegistryKey m_key; + SimpleRegistryImpl* m_pRegistry; +}; + +//************************************************************************* +RegistryKeyImpl::RegistryKeyImpl( const RegistryKey& key, SimpleRegistryImpl* pRegistry ) + : m_key(key) + , m_pRegistry(pRegistry) +{ + m_pRegistry->acquire(); + m_name = m_key.getName(); +} + +//************************************************************************* +RegistryKeyImpl::RegistryKeyImpl( const OUString& rKeyName, + SimpleRegistryImpl* pRegistry ) + : m_pRegistry(pRegistry) +{ + m_pRegistry->acquire(); + + RegistryKey rootKey; + if (!pRegistry->m_registry.isValid() || + pRegistry->m_registry.openRootKey(rootKey)) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + if ( rootKey.openKey(rKeyName, m_key) ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + m_name = rKeyName; + } + } +} + +//************************************************************************* +RegistryKeyImpl::~RegistryKeyImpl() +{ + m_pRegistry->release(); +} + +//************************************************************************* +OUString SAL_CALL RegistryKeyImpl::getKeyName() throw(RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + return m_name; +} + +//************************************************************************* +sal_Bool SAL_CALL RegistryKeyImpl::isReadOnly( ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if (m_key.isValid()) + { + return(m_key.isReadOnly()); + } else + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } +} + +//************************************************************************* +sal_Bool SAL_CALL RegistryKeyImpl::isValid( ) throw(RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + return m_key.isValid(); +} + +//************************************************************************* +RegistryKeyType SAL_CALL RegistryKeyImpl::getKeyType( const OUString& rKeyName ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( m_key.isValid() ) + { + RegKeyType keyType; + if ( !m_key.getKeyType(rKeyName, &keyType) ) + { + switch (keyType) + { + case RG_KEYTYPE: + return RegistryKeyType_KEY; + case RG_LINKTYPE: + return RegistryKeyType_LINK; + } + } else + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } + } else + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } + + return RegistryKeyType_KEY; +} + +//************************************************************************* +RegistryValueType SAL_CALL RegistryKeyImpl::getValueType( ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if (!m_key.isValid()) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + RegValueType type; + sal_uInt32 size; + + if (m_key.getValueInfo(OUString(), &type, &size)) + { + return RegistryValueType_NOT_DEFINED; + } else + { + switch (type) + { + case RG_VALUETYPE_LONG: return RegistryValueType_LONG; + case RG_VALUETYPE_STRING: return RegistryValueType_ASCII; + case RG_VALUETYPE_UNICODE: return RegistryValueType_STRING; + case RG_VALUETYPE_BINARY: return RegistryValueType_BINARY; + case RG_VALUETYPE_LONGLIST: return RegistryValueType_LONGLIST; + case RG_VALUETYPE_STRINGLIST: return RegistryValueType_ASCIILIST; + case RG_VALUETYPE_UNICODELIST: return RegistryValueType_STRINGLIST; + default: return RegistryValueType_NOT_DEFINED; + } + } + } + + return RegistryValueType_NOT_DEFINED; +} + +//************************************************************************* +sal_Int32 SAL_CALL RegistryKeyImpl::getLongValue( ) + throw(InvalidRegistryException, InvalidValueException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if (!m_key.isValid()) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + RegValueType type; + sal_uInt32 size; + + if ( !m_key.getValueInfo(OUString(), &type, &size) ) + { + if (type == RG_VALUETYPE_LONG) + { + sal_Int32 value; + if ( !m_key.getValue(OUString(), (RegValue)&value) ) + { + return value; + } + } + } + + throw InvalidValueException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidValueException") ), + (OWeakObject *)this ); + } +} + +//************************************************************************* +void SAL_CALL RegistryKeyImpl::setLongValue( sal_Int32 value ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_key.isValid() ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + if (m_key.setValue(OUString(), RG_VALUETYPE_LONG, &value, sizeof(sal_Int32))) + { + throw InvalidValueException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidValueException") ), + (OWeakObject *)this ); + } + } +} + +//************************************************************************* +Sequence< sal_Int32 > SAL_CALL RegistryKeyImpl::getLongListValue( ) + throw(InvalidRegistryException, InvalidValueException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_key.isValid() ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + RegValueType type; + sal_uInt32 size; + + if ( !m_key.getValueInfo(OUString(), &type, &size) ) + { + if (type == RG_VALUETYPE_LONGLIST) + { + RegistryValueList<sal_Int32> tmpValue; + if ( !m_key.getLongListValue(OUString(), tmpValue) ) + { + Sequence<sal_Int32> seqValue(size); + + for (sal_uInt32 i=0; i < size; i++) + { + seqValue.getArray()[i] = tmpValue.getElement(i); + } + + return seqValue; + } + } + } + + throw InvalidValueException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidValueException") ), + (OWeakObject *)this ); + } +} + +//************************************************************************* +void SAL_CALL RegistryKeyImpl::setLongListValue( const Sequence< sal_Int32 >& seqValue ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_key.isValid() ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + sal_uInt32 length = seqValue.getLength(); + sal_Int32* tmpValue = new sal_Int32[length]; + + for (sal_uInt32 i=0; i < length; i++) + { + tmpValue[i] = seqValue.getConstArray()[i]; + } + + if ( m_key.setLongListValue(OUString(), tmpValue, length) ) + { + delete[] tmpValue; + throw InvalidValueException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidValueException") ), + (OWeakObject *)this ); + } + + delete[] tmpValue; + } +} + +//************************************************************************* +OUString SAL_CALL RegistryKeyImpl::getAsciiValue( ) + throw(InvalidRegistryException, InvalidValueException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if (!m_key.isValid()) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + RegValueType type; + sal_uInt32 size; + + if ( !m_key.getValueInfo(OUString(), &type, &size) ) + { + if ( type == RG_VALUETYPE_STRING ) + { + char* value = new char[size]; + if ( m_key.getValue(OUString(), (RegValue)value) ) + { + delete [] value; + throw InvalidValueException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidValueException") ), + (OWeakObject *)this ); + } else + { + OUString ret(OStringToOUString(value, RTL_TEXTENCODING_UTF8)); + delete [] value; + return ret; + } + } + } + + throw InvalidValueException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidValueException") ), + (OWeakObject *)this ); + } +} + +//************************************************************************* +void SAL_CALL RegistryKeyImpl::setAsciiValue( const OUString& value ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_key.isValid() ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + OString sValue = OUStringToOString(value, RTL_TEXTENCODING_UTF8); + sal_uInt32 size = sValue.getLength()+1; + if ( m_key.setValue(OUString(), RG_VALUETYPE_STRING, + (RegValue)(sValue.getStr()), size) ) + { + throw InvalidValueException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidValueException") ), + (OWeakObject *)this ); + } + } +} + +//************************************************************************* +Sequence< OUString > SAL_CALL RegistryKeyImpl::getAsciiListValue( ) + throw(InvalidRegistryException, InvalidValueException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_key.isValid() ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + RegValueType type; + sal_uInt32 size; + + if ( !m_key.getValueInfo(OUString(), &type, &size) ) + { + if (type == RG_VALUETYPE_STRINGLIST) + { + RegistryValueList<char*> tmpValue; + if ( !m_key.getStringListValue(OUString(), tmpValue) ) + { + Sequence<OUString> seqValue(size); + + for (sal_uInt32 i=0; i < size; i++) + { + seqValue.getArray()[i] = + OStringToOUString(tmpValue.getElement(i), RTL_TEXTENCODING_UTF8); + } + + return seqValue; + } + } + } + + throw InvalidValueException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidValueException") ), + (OWeakObject *)this ); + } +} + +//************************************************************************* +void SAL_CALL RegistryKeyImpl::setAsciiListValue( const Sequence< OUString >& seqValue ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_key.isValid() ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + sal_uInt32 length = seqValue.getLength(); + OString* pSValue = new OString[length]; + char** tmpValue = new char*[length]; + + for (sal_uInt32 i=0; i < length; i++) + { + pSValue[i] = OUStringToOString(seqValue.getConstArray()[i], RTL_TEXTENCODING_UTF8); + tmpValue[i] = (char*)pSValue[i].getStr(); + } + + if ( m_key.setStringListValue(OUString(), tmpValue, length) ) + { + delete[] pSValue; + delete[] tmpValue; + throw InvalidValueException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidValueException") ), + (OWeakObject *)this ); + } + + delete[] pSValue; + delete[] tmpValue; + } +} + +//************************************************************************* +OUString SAL_CALL RegistryKeyImpl::getStringValue( ) + throw(InvalidRegistryException, InvalidValueException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_key.isValid() ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + RegValueType type; + sal_uInt32 size; + + if ( !m_key.getValueInfo(OUString(), &type, &size) ) + { + if (type == RG_VALUETYPE_UNICODE) + { + sal_Unicode* value = new sal_Unicode[size]; + if ( m_key.getValue(OUString(), (RegValue)value) ) + { + delete [] value; + throw InvalidValueException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidValueException") ), + (OWeakObject *)this ); + } else + { + OUString ret(value); + delete [] value; + return ret; + } + } + } + + throw InvalidValueException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidValueException") ), + (OWeakObject *)this ); + } +} + +//************************************************************************* +void SAL_CALL RegistryKeyImpl::setStringValue( const OUString& value ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_key.isValid() ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + sal_uInt32 size = (value.getLength() + 1) * sizeof(sal_Unicode); + if ( m_key.setValue(OUString(), RG_VALUETYPE_UNICODE, + (RegValue)(value.getStr()), size) ) + { + throw InvalidValueException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidValueException") ), + (OWeakObject *)this ); + } + } +} + +//************************************************************************* +Sequence< OUString > SAL_CALL RegistryKeyImpl::getStringListValue( ) + throw(InvalidRegistryException, InvalidValueException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_key.isValid() ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + RegValueType type; + sal_uInt32 size; + + if ( !m_key.getValueInfo(OUString(), &type, &size) ) + { + if (type == RG_VALUETYPE_UNICODELIST) + { + RegistryValueList<sal_Unicode*> tmpValue; + if ( !m_key.getUnicodeListValue(OUString(), tmpValue) ) + { + Sequence<OUString> seqValue(size); + + for (sal_uInt32 i=0; i < size; i++) + { + seqValue.getArray()[i] = OUString(tmpValue.getElement(i)); + } + + return seqValue; + } + } + } + + throw InvalidValueException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidValueException") ), + (OWeakObject *)this ); + } +} + +//************************************************************************* +void SAL_CALL RegistryKeyImpl::setStringListValue( const Sequence< OUString >& seqValue ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_key.isValid() ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + sal_uInt32 length = seqValue.getLength(); + sal_Unicode** tmpValue = new sal_Unicode*[length]; + + for (sal_uInt32 i=0; i < length; i++) + { + tmpValue[i] = (sal_Unicode*)seqValue.getConstArray()[i].getStr(); + } + + if (m_key.setUnicodeListValue(OUString(), tmpValue, length)) + { + delete[] tmpValue; + throw InvalidValueException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidValueException") ), + (OWeakObject *)this ); + } + + delete[] tmpValue; + } +} + +//************************************************************************* +Sequence< sal_Int8 > SAL_CALL RegistryKeyImpl::getBinaryValue( ) + throw(InvalidRegistryException, InvalidValueException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_key.isValid() ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + RegValueType type; + sal_uInt32 size; + + if ( !m_key.getValueInfo(OUString(), &type, &size) ) + { + if (type == RG_VALUETYPE_BINARY) + { + sal_Int8* value = new sal_Int8[size]; + if (m_key.getValue(OUString(), (RegValue)value)) + { + delete [] value; + throw InvalidValueException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidValueException") ), + (OWeakObject *)this ); + } else + { + Sequence<sal_Int8> seqBytes(value, size); + delete [] value; + return seqBytes; + } + } + } + + throw InvalidValueException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidValueException") ), + (OWeakObject *)this ); + } +} + +//************************************************************************* +void SAL_CALL RegistryKeyImpl::setBinaryValue( const Sequence< sal_Int8 >& value ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_key.isValid() ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + sal_uInt32 size = value.getLength(); + if ( m_key.setValue(OUString(), RG_VALUETYPE_BINARY, + (RegValue)(value.getConstArray()), size) ) + { + throw InvalidValueException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidValueException") ), + (OWeakObject *)this ); + } + } +} + +//************************************************************************* +Reference< XRegistryKey > SAL_CALL RegistryKeyImpl::openKey( const OUString& aKeyName ) + throw(InvalidRegistryException, RuntimeException) +{ + RegistryKey newKey; + + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_key.isValid() ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + RegError _ret = m_key.openKey(aKeyName, newKey); + if ( _ret ) + { + if ( _ret == REG_INVALID_KEY ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } + + return Reference<XRegistryKey>(); + } else + { + return ((XRegistryKey*)new RegistryKeyImpl(newKey, m_pRegistry)); + } + } +} + +//************************************************************************* +Reference< XRegistryKey > SAL_CALL RegistryKeyImpl::createKey( const OUString& aKeyName ) + throw(InvalidRegistryException, RuntimeException) +{ + RegistryKey newKey; + + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_key.isValid() ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + RegError _ret = m_key.createKey(aKeyName, newKey); + if ( _ret ) + { + if (_ret == REG_INVALID_KEY) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } + + return Reference<XRegistryKey>(); + } else + { + return ((XRegistryKey*)new RegistryKeyImpl(newKey, m_pRegistry)); + } + } +} + +//************************************************************************* +void SAL_CALL RegistryKeyImpl::closeKey( ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( m_key.isValid() ) + { + if ( !m_key.closeKey() ) + return; + } + + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); +} + +//************************************************************************* +void SAL_CALL RegistryKeyImpl::deleteKey( const OUString& rKeyName ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( m_key.isValid() ) + { + if ( !m_key.deleteKey(rKeyName) ) + return; + } + + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); +} + +//************************************************************************* +Sequence< Reference< XRegistryKey > > SAL_CALL RegistryKeyImpl::openKeys( ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_key.isValid() ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + RegistryKeyArray subKeys; + RegError _ret = REG_NO_ERROR; + if ( (_ret = m_key.openSubKeys(OUString(), subKeys)) ) + { + if ( _ret == REG_INVALID_KEY ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } + + return Sequence< Reference<XRegistryKey> >(); + } else + { + sal_uInt32 length = subKeys.getLength(); + Sequence< Reference<XRegistryKey> > seqKeys(length); + + for (sal_uInt32 i=0; i < length; i++) + { + seqKeys.getArray()[i] = + (XRegistryKey*) new RegistryKeyImpl(subKeys.getElement(i), m_pRegistry); + } + return seqKeys; + } + } +} + +//************************************************************************* +Sequence< OUString > SAL_CALL RegistryKeyImpl::getKeyNames( ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_key.isValid() ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + RegistryKeyNames subKeys; + RegError _ret = REG_NO_ERROR; + if ( (_ret = m_key.getKeyNames(OUString(), subKeys)) ) + { + if ( _ret == REG_INVALID_KEY ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } + + return Sequence<OUString>(); + } else + { + sal_uInt32 length = subKeys.getLength(); + Sequence<OUString> seqKeys(length); + + for (sal_uInt32 i=0; i < length; i++) + { + seqKeys.getArray()[i] = subKeys.getElement(i); + } + return seqKeys; + } + } +} + +//************************************************************************* +sal_Bool SAL_CALL RegistryKeyImpl::createLink( const OUString& aLinkName, const OUString& aLinkTarget ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_key.isValid() ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + RegError ret = m_key.createLink(aLinkName, aLinkTarget); + if ( ret ) + { + if ( ret == REG_DETECT_RECURSION || + ret == REG_INVALID_KEY ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + return sal_False; + } + } + } + return sal_True; +} + +//************************************************************************* +void SAL_CALL RegistryKeyImpl::deleteLink( const OUString& rLinkName ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_key.isValid() ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + if ( m_key.deleteLink(rLinkName) ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } + } +} + +//************************************************************************* +OUString SAL_CALL RegistryKeyImpl::getLinkTarget( const OUString& rLinkName ) + throw(InvalidRegistryException, RuntimeException) +{ + OUString linkTarget; + + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_key.isValid() ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + RegError ret = m_key.getLinkTarget(rLinkName, linkTarget); + if ( ret ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } + } + + return linkTarget; +} + +//************************************************************************* +OUString SAL_CALL RegistryKeyImpl::getResolvedName( const OUString& aKeyName ) + throw(InvalidRegistryException, RuntimeException) +{ + OUString resolvedName; + + Guard< Mutex > aGuard( m_pRegistry->m_mutex ); + if ( !m_key.isValid() ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } else + { + RegError ret = m_key.getResolvedKeyName( + aKeyName, sal_True, resolvedName); + if ( ret ) + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } + } + + return resolvedName; +} + +//************************************************************************* +SimpleRegistryImpl::SimpleRegistryImpl( const Registry& rRegistry ) + : m_registry(rRegistry) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); +} + +//************************************************************************* +SimpleRegistryImpl::~SimpleRegistryImpl() +{ + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + +//************************************************************************* +OUString SAL_CALL SimpleRegistryImpl::getImplementationName( ) + throw(RuntimeException) +{ + return stoc_bootstrap::simreg_getImplementationName(); +} + +//************************************************************************* +sal_Bool SAL_CALL SimpleRegistryImpl::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 SimpleRegistryImpl::getSupportedServiceNames( ) + throw(RuntimeException) +{ + return stoc_bootstrap::simreg_getSupportedServiceNames(); +} + +//************************************************************************* +OUString SAL_CALL SimpleRegistryImpl::getURL() throw(RuntimeException) +{ + Guard< Mutex > aGuard( m_mutex ); + return m_url; +} + +//************************************************************************* +void SAL_CALL SimpleRegistryImpl::open( const OUString& rURL, sal_Bool bReadOnly, sal_Bool bCreate ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_mutex ); + if ( m_registry.isValid() ) + { + m_registry.close(); + } + + RegAccessMode accessMode = REG_READWRITE; + + if ( bReadOnly ) + accessMode = REG_READONLY; + + if ( !m_registry.open(rURL, accessMode) ) + { + m_url = rURL; + return; + } + + if ( bCreate ) + { + if ( !m_registry.create(rURL) ) + { + m_url = rURL; + return; + } + } + + m_url = OUString(); + + OUStringBuffer reason( 128 ); + reason.appendAscii( RTL_CONSTASCII_STRINGPARAM("Couldn't ") ); + if( bCreate ) + { + reason.appendAscii( RTL_CONSTASCII_STRINGPARAM("create") ); + } + else + { + reason.appendAscii( RTL_CONSTASCII_STRINGPARAM("open") ); + } + reason.appendAscii( RTL_CONSTASCII_STRINGPARAM(" registry ") ); + reason.append( rURL ); + if( bReadOnly ) + { + reason.appendAscii( RTL_CONSTASCII_STRINGPARAM(" for reading") ); + } + else + { + reason.appendAscii( RTL_CONSTASCII_STRINGPARAM(" for writing" ) ); + } + throw InvalidRegistryException( reason.makeStringAndClear() , Reference< XInterface >() ); +} + +//************************************************************************* +sal_Bool SAL_CALL SimpleRegistryImpl::isValid( ) throw(RuntimeException) +{ + Guard< Mutex > aGuard( m_mutex ); + return m_registry.isValid(); +} + +//************************************************************************* +void SAL_CALL SimpleRegistryImpl::close( ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_mutex ); + if ( m_registry.isValid() ) + { + if ( !m_registry.close() ) + { + m_url = OUString(); + return; + } + } + + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); +} + +//************************************************************************* +void SAL_CALL SimpleRegistryImpl::destroy( ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_mutex ); + if ( m_registry.isValid() ) + { + if ( !m_registry.destroy(OUString()) ) + { + m_url = OUString(); + return; + } + } + + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); +} + +//************************************************************************* +Reference< XRegistryKey > SAL_CALL SimpleRegistryImpl::getRootKey( ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_mutex ); + if ( m_registry.isValid() ) + return ((XRegistryKey*)new RegistryKeyImpl(OUString( RTL_CONSTASCII_USTRINGPARAM("/") ), this)); + else + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } +} + +//************************************************************************* +sal_Bool SAL_CALL SimpleRegistryImpl::isReadOnly( ) + throw(InvalidRegistryException, RuntimeException) +{ + Guard< Mutex > aGuard( m_mutex ); + if ( m_registry.isValid() ) + return m_registry.isReadOnly(); + else + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } +} + +//************************************************************************* +void SAL_CALL SimpleRegistryImpl::mergeKey( const OUString& aKeyName, const OUString& aUrl ) + throw(InvalidRegistryException, MergeConflictException, RuntimeException) +{ + Guard< Mutex > aGuard( m_mutex ); + if ( m_registry.isValid() ) + { + RegistryKey rootKey; + if ( !m_registry.openRootKey(rootKey) ) + { + RegError ret = m_registry.mergeKey(rootKey, aKeyName, aUrl, sal_False, sal_False); + if (ret) + { + if ( ret == REG_MERGE_CONFLICT ) + return; + if ( ret == REG_MERGE_ERROR ) + { + throw MergeConflictException( + OUString( RTL_CONSTASCII_USTRINGPARAM("MergeConflictException") ), + (OWeakObject *)this ); + } + else + { + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); + } + } + + return; + } + } + + throw InvalidRegistryException( + OUString( RTL_CONSTASCII_USTRINGPARAM("InvalidRegistryException") ), + (OWeakObject *)this ); +} +} + +namespace stoc_bootstrap +{ +//************************************************************************* +Reference<XInterface> SAL_CALL SimpleRegistry_CreateInstance( const Reference<XComponentContext>& ) +{ + Reference<XInterface> xRet; + + Registry reg; + + XSimpleRegistry *pRegistry = (XSimpleRegistry*) new stoc_simreg::SimpleRegistryImpl(reg); + + if (pRegistry) + { + xRet = Reference<XInterface>::query(pRegistry); + } + + return xRet; +} +} + 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..5a276293089a --- /dev/null +++ b/stoc/source/stocservices/stocservices.cxx @@ -0,0 +1,117 @@ +/************************************************************************* + * + * 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; +} +//================================================================================================== +sal_Bool SAL_CALL component_writeInfo( + void * pServiceManager, void * pRegistryKey ) +{ + return component_writeInfoHelper( pServiceManager, pRegistryKey, g_entries ); +} +//================================================================================================== +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 diff --git a/stoc/test/excomp/example/ExampleComponent1.idl b/stoc/test/excomp/example/ExampleComponent1.idl new file mode 100644 index 000000000000..6ebf2a7e4eb7 --- /dev/null +++ b/stoc/test/excomp/example/ExampleComponent1.idl @@ -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 _EXCOMP_EXAMPLECOMPONENT1_IDL_ +#define _EXCOMP_EXAMPLECOMPONENT1_IDL_ + +#include <example/XTest.idl> + +module example +{ + +service ExampleComponent1 +{ + interface XTest; +}; + +}; // test + + +#endif diff --git a/stoc/test/excomp/example/ExampleComponent2.idl b/stoc/test/excomp/example/ExampleComponent2.idl new file mode 100644 index 000000000000..ff2b3b28c5d0 --- /dev/null +++ b/stoc/test/excomp/example/ExampleComponent2.idl @@ -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 _EXCOMP_EXAMPLECOMPONENT2_IDL_ +#define _EXCOMP_EXAMPLECOMPONENT2_IDL_ + +#include <example/XTest.idl> + +module example +{ + +service ExampleComponent2 +{ + interface XTest; +}; + +}; // test + + +#endif diff --git a/stoc/test/excomp/example/XTest.idl b/stoc/test/excomp/example/XTest.idl new file mode 100644 index 000000000000..8bf578b10d29 --- /dev/null +++ b/stoc/test/excomp/example/XTest.idl @@ -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. + * + ************************************************************************/ +#ifndef _EXCOMP_XTEST_IDL_ +#define _EXCOMP_XTEST_IDL_ + +#include <com/sun/star/uno/XInterface.idl> + +module example +{ +/** + * Simple test interface. + * + * @author Juergen Schmidt + */ +interface XTest : com::sun::star::uno::XInterface +{ + /** + * in parameter test, tests by calls reference also (complex types) + */ + string getMessage( ); +}; + +}; // test + +#endif diff --git a/stoc/test/excomp/excomp.cxx b/stoc/test/excomp/excomp.cxx new file mode 100644 index 000000000000..bdfa520a6e39 --- /dev/null +++ b/stoc/test/excomp/excomp.cxx @@ -0,0 +1,136 @@ +/************************************************************************* + * + * 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <sal/main.h> +#include <osl/diagnose.h> +#include <osl/process.h> + +#include <example/XTest.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/registry/XImplementationRegistration.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/servicefactory.hxx> + + +using namespace com::sun::star::uno; +using namespace com::sun::star::registry; +using namespace com::sun::star::lang; +using namespace example; +using namespace cppu; +using namespace rtl; + +#if OSL_DEBUG_LEVEL > 0 +#define TEST_ENSHURE(c, m) OSL_ENSURE(c, m) +#else +#define TEST_ENSHURE(c, m) OSL_VERIFY(c) +#endif + +OUString getExePath() +{ + OUString exe; + + OSL_VERIFY(osl_getExecutableFile( &exe.pData) == osl_Process_E_None); + +#if defined(WIN32) || defined(__OS2__) || defined(WNT) + exe = exe.copy(0, exe.getLength() - 10); +#else + exe = exe.copy(0, exe.getLength() - 6); +#endif + return exe; +} + +SAL_IMPLEMENT_MAIN() +{ +#ifdef UNX + OUString compName1(RTL_CONSTASCII_USTRINGPARAM("libexcomp1.so")); + OUString compName2(RTL_CONSTASCII_USTRINGPARAM("libexcomp2.so")); +#else + OUString compName1(RTL_CONSTASCII_USTRINGPARAM("excomp1")); + OUString compName2(RTL_CONSTASCII_USTRINGPARAM("excomp2")); +#endif + + OUString exePath( getExePath() ); + OUString excompRdb(exePath); + + excompRdb += OUString::createFromAscii("excomp.rdb"); + + Reference< XMultiServiceFactory > xSMgr = ::cppu::createRegistryServiceFactory( excompRdb ); + TEST_ENSHURE( xSMgr.is(), "excomp error 0" ); + + typelib_TypeDescription* pTypeDesc = NULL; + OUString sType = OUString::createFromAscii("com.sun.star.text.XTextDocument"); + typelib_typedescription_getByName( &pTypeDesc, sType.pData); +// typelib_InterfaceTypeDescription* pInterDesc = (typelib_InterfaceTypeDescription*)pTypeDesc; + + Reference< XInterface > xIFace = xSMgr->createInstance(OUString::createFromAscii("com.sun.star.registry.ImplementationRegistration")); + Reference< XImplementationRegistration > xImpReg( xIFace, UNO_QUERY); + TEST_ENSHURE( xImpReg.is(), "excomp error 1" ); + try + { + xImpReg->registerImplementation(OUString::createFromAscii("com.sun.star.loader.SharedLibrary"), + compName1, + Reference< XSimpleRegistry >() ); + xImpReg->registerImplementation(OUString::createFromAscii("com.sun.star.loader.SharedLibrary"), + compName2, + Reference< XSimpleRegistry >() ); + } + catch( CannotRegisterImplementationException& e) + { + TEST_ENSHURE( e.Message.getLength(), OUStringToOString(e.Message, RTL_TEXTENCODING_ASCII_US).getStr() ); + } + + Reference< XTest > xTest1( xSMgr->createInstance(OUString::createFromAscii("example.ExampleComponent1")), + UNO_QUERY); + TEST_ENSHURE( xTest1.is(), "excomp error 2" ); + Reference< XTest > xTest2( xSMgr->createInstance(OUString::createFromAscii("example.ExampleComponent2")), + UNO_QUERY); + TEST_ENSHURE( xTest2.is(), "excomp error 3" ); + + OUString m1 = xTest1->getMessage(); + OUString m2 = xTest2->getMessage(); + + fprintf(stdout, "ExampleComponent1, Message = \"%s\"\n", OUStringToOString(m1, RTL_TEXTENCODING_ASCII_US).getStr()); + fprintf(stdout, "ExampleComponent2, Message = \"%s\"\n", OUStringToOString(m2, RTL_TEXTENCODING_ASCII_US).getStr()); + + xImpReg->revokeImplementation(compName1, Reference< XSimpleRegistry >() ); + xImpReg->revokeImplementation(compName2, Reference< XSimpleRegistry >() ); + + Reference< XComponent >( xSMgr, UNO_QUERY )->dispose(); + + return(0); +} + + diff --git a/stoc/test/excomp/excomp1.cxx b/stoc/test/excomp/excomp1.cxx new file mode 100644 index 000000000000..210bee770cc9 --- /dev/null +++ b/stoc/test/excomp/excomp1.cxx @@ -0,0 +1,215 @@ +/************************************************************************* + * + * 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/alloc.h> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/implbase2.hxx> + +#include <example/XTest.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> + +using namespace example; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::registry; +using namespace cppu; +using namespace osl; +using namespace rtl; + +#define SERVICENAME1 "example.ExampleComponent1" +#define IMPLNAME1 "example.ExampleComponent1.Impl" + +namespace excomp_impl { + +//************************************************************************* +// ExampleComponent1Impl +//************************************************************************* +class ExampleComponent1Impl : public WeakImplHelper2< XTest, XServiceInfo > +{ +public: + ExampleComponent1Impl( const Reference<XMultiServiceFactory> & rXSMgr ); + + ~ExampleComponent1Impl(); + + // 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); + static Sequence< OUString > SAL_CALL getSupportedServiceNames_Static( ); + + // XSimpleRegistry + virtual OUString SAL_CALL getMessage() throw(RuntimeException); + +protected: + Mutex m_mutex; + + Reference<XMultiServiceFactory> m_xSMgr; +}; + +//************************************************************************* +ExampleComponent1Impl::ExampleComponent1Impl( const Reference<XMultiServiceFactory> & rXSMgr ) + : m_xSMgr(rXSMgr) +{ +} + +//************************************************************************* +ExampleComponent1Impl::~ExampleComponent1Impl() +{ +} + +//************************************************************************* +OUString SAL_CALL ExampleComponent1Impl::getImplementationName( ) + throw(RuntimeException) +{ + Guard< Mutex > aGuard( m_mutex ); + return OUString( RTL_CONSTASCII_USTRINGPARAM(IMPLNAME1) ); +} + +//************************************************************************* +sal_Bool SAL_CALL ExampleComponent1Impl::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 ExampleComponent1Impl::getSupportedServiceNames( ) + throw(RuntimeException) +{ + Guard< Mutex > aGuard( m_mutex ); + return getSupportedServiceNames_Static(); +} + +//************************************************************************* +Sequence<OUString> SAL_CALL ExampleComponent1Impl::getSupportedServiceNames_Static( ) +{ + OUString aName( RTL_CONSTASCII_USTRINGPARAM(SERVICENAME1) ); + return Sequence< OUString >( &aName, 1 ); +} + +//************************************************************************* +OUString SAL_CALL ExampleComponent1Impl::getMessage() throw(RuntimeException) +{ + Guard< Mutex > aGuard( m_mutex ); + return OUString::createFromAscii("Lalelu nur der Mann im Mond schaut zu ..."); +} + + +//************************************************************************* +Reference<XInterface> SAL_CALL ExampleComponent1_CreateInstance( const Reference<XMultiServiceFactory>& rSMgr ) +{ + Reference<XInterface> xRet; + + XTest *pXTest = (XTest*) new ExampleComponent1Impl(rSMgr); + + if (pXTest) + { + xRet = Reference< XInterface >::query(pXTest); + } + + return xRet; +} + +} // excomp_impl + + +extern "C" +{ +//================================================================================================== +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} +//================================================================================================== +sal_Bool SAL_CALL component_writeInfo( + void * /* pServiceManager */ , void * pRegistryKey ) +{ + if (pRegistryKey) + { + try + { + // ExampleComponent1 + Reference< XRegistryKey > xNewKey( + reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey( + OUString( RTL_CONSTASCII_USTRINGPARAM("/" IMPLNAME1 "/UNO/SERVICES") ) ) ); + + const Sequence< OUString > & rSNL = + ::excomp_impl::ExampleComponent1Impl::getSupportedServiceNames_Static(); + const OUString * pArray = rSNL.getConstArray(); + for ( sal_Int32 nPos = rSNL.getLength(); nPos--; ) + xNewKey->createKey( pArray[nPos] ); + + return sal_True; + } + catch (InvalidRegistryException &) + { + OSL_ENSURE( sal_False, "### InvalidRegistryException!" ); + } + } + return sal_False; +} +//================================================================================================== +void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * /* pRegistryKey */ ) +{ + void * pRet = 0; + + if (rtl_str_compare( pImplName, IMPLNAME1 ) == 0) + { + Reference< XSingleServiceFactory > xFactory( createSingleFactory( + reinterpret_cast< XMultiServiceFactory * >( pServiceManager ), + OUString( RTL_CONSTASCII_USTRINGPARAM(IMPLNAME1) ), + ::excomp_impl::ExampleComponent1_CreateInstance, + ::excomp_impl::ExampleComponent1Impl::getSupportedServiceNames_Static() ) ); + + if (xFactory.is()) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } + + return pRet; +} +} + + + diff --git a/stoc/test/excomp/excomp1.xml b/stoc/test/excomp/excomp1.xml new file mode 100644 index 000000000000..80b6cb0450f9 --- /dev/null +++ b/stoc/test/excomp/excomp1.xml @@ -0,0 +1,33 @@ +<?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> excomp1 </module-name> + <component-description> + <author> Juergen Schmidt </author> + <name> example.ExampleComponent1.Impl </name> + <description> + This component provides a simple demo component. +</description> + <loader-name> com.sun.star.loader.SharedLibrary </loader-name> + <language> c++ </language> + <status value="final"/> + <supported-service> example.ExampleComponent1 </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.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> example.XTest </type> + </component-description> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> vos </project-build-dependency> + <project-build-dependency> sal </project-build-dependency> + <runtime-module-dependency> cppuhelper </runtime-module-dependency> + <runtime-module-dependency> cppu </runtime-module-dependency> + <runtime-module-dependency> vos </runtime-module-dependency> + <runtime-module-dependency> sal </runtime-module-dependency> +</module-description> diff --git a/stoc/test/excomp/excomp2.cxx b/stoc/test/excomp/excomp2.cxx new file mode 100644 index 000000000000..3595b6ecda06 --- /dev/null +++ b/stoc/test/excomp/excomp2.cxx @@ -0,0 +1,286 @@ +/************************************************************************* + * + * 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/alloc.h> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/weak.hxx> +#include <cppuhelper/typeprovider.hxx> + +#include <example/XTest.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/registry/XRegistryKey.hpp> + +using namespace example; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::registry; +using namespace cppu; +using namespace osl; +using namespace rtl; + +#define SERVICENAME2 "example.ExampleComponent2" +#define IMPLNAME2 "example.ExampleComponent2.Impl" + +namespace excomp2_impl { + +//************************************************************************* +// ExampleComponent2Impl +//************************************************************************* +class ExampleComponent2Impl : public OWeakObject + , public XTypeProvider + , public XServiceInfo + , public XTest +{ +public: + ExampleComponent2Impl( const Reference<XMultiServiceFactory> & rXSMgr ); + + ~ExampleComponent2Impl(); + + // XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface( const ::com::sun::star::uno::Type & rType ) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL acquire() throw() + { OWeakObject::acquire(); } + virtual void SAL_CALL release() throw() + { OWeakObject::release(); } + + // XTypeProvider + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getTypes() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException); + + // 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); + static Sequence< OUString > SAL_CALL getSupportedServiceNames_Static( ); + + // XTest + virtual OUString SAL_CALL getMessage() throw(RuntimeException); + +protected: + Mutex m_mutex; + + Reference<XMultiServiceFactory> m_xSMgr; +}; + +//************************************************************************* +ExampleComponent2Impl::ExampleComponent2Impl( const Reference<XMultiServiceFactory> & rXSMgr ) + : m_xSMgr(rXSMgr) +{ +} + +//************************************************************************* +ExampleComponent2Impl::~ExampleComponent2Impl() +{ +} + +//************************************************************************* +Any SAL_CALL ExampleComponent2Impl::queryInterface( const ::com::sun::star::uno::Type & rType ) + throw(::com::sun::star::uno::RuntimeException) +{ + Any aRet = ::cppu::queryInterface(rType, + static_cast< XTypeProvider * >( this ), + static_cast< XServiceInfo * >( this ), + static_cast< XTest * >( this ) ); + if ( aRet.hasValue() ) + return aRet; + + return OWeakObject::queryInterface( rType ); +} + +//************************************************************************* +Sequence< Type > SAL_CALL ExampleComponent2Impl::getTypes() + throw (::com::sun::star::uno::RuntimeException) +{ + static OTypeCollection * pTypes = 0; + if (! pTypes) + { + MutexGuard aGuard( m_mutex ); + if (! pTypes) + { + static OTypeCollection aTypes( + ::getCppuType( (const Reference< XInterface > *)0 ), + ::getCppuType( (const Reference< XWeak > *)0 ), + ::getCppuType( (const Reference< XTypeProvider > *)0 ), + ::getCppuType( (const Reference< XServiceInfo > *)0 ), + ::getCppuType( (const Reference< XTest > *)0 ) ); + pTypes = &aTypes; + } + } + return pTypes->getTypes(); +} + +//************************************************************************* +Sequence< sal_Int8 > SAL_CALL ExampleComponent2Impl::getImplementationId() + throw (::com::sun::star::uno::RuntimeException) +{ + static OImplementationId * pId = 0; + if (! pId) + { + MutexGuard aGuard( m_mutex ); + if (! pId) + { + static OImplementationId aId; + pId = &aId; + } + } + return pId->getImplementationId(); +} + +//************************************************************************* +OUString SAL_CALL ExampleComponent2Impl::getImplementationName( ) + throw(RuntimeException) +{ + Guard< Mutex > aGuard( m_mutex ); + return OUString( RTL_CONSTASCII_USTRINGPARAM(IMPLNAME2) ); +} + +//************************************************************************* +sal_Bool SAL_CALL ExampleComponent2Impl::supportsService( const OUString& ServiceName ) + throw(RuntimeException) +{ + Guard< Mutex > aGuard( m_mutex ); + 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; +} + +//************************************************************************* +Sequence<OUString> SAL_CALL ExampleComponent2Impl::getSupportedServiceNames( ) + throw(RuntimeException) +{ + Guard< Mutex > aGuard( m_mutex ); + return getSupportedServiceNames_Static(); +} + +//************************************************************************* +Sequence<OUString> SAL_CALL ExampleComponent2Impl::getSupportedServiceNames_Static( ) +{ + OUString aName( RTL_CONSTASCII_USTRINGPARAM(SERVICENAME2) ); + return Sequence< OUString >( &aName, 1 ); +} + +//************************************************************************* +OUString SAL_CALL ExampleComponent2Impl::getMessage() throw(RuntimeException) +{ + Guard< Mutex > aGuard( m_mutex ); + return OUString::createFromAscii("Alle meine Entchen schwimmen auf dem See, schwimmen auf dem See ..."); +} + + +//************************************************************************* +Reference<XInterface> SAL_CALL ExampleComponent2_CreateInstance( const Reference<XMultiServiceFactory>& rSMgr ) +{ + Reference<XInterface> xRet; + + XTest *pXTest = (XTest*) new ExampleComponent2Impl(rSMgr); + + if (pXTest) + { + xRet = Reference< XInterface >::query(pXTest); + } + + return xRet; +} + + +} // excomp_impl + + +extern "C" +{ +//================================================================================================== +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} +//================================================================================================== +sal_Bool SAL_CALL component_writeInfo( + void * /* pServiceManager */, void * pRegistryKey ) +{ + if (pRegistryKey) + { + try + { + // ExampleComponent2 + Reference< XRegistryKey > xNewKey( + reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey( + OUString( RTL_CONSTASCII_USTRINGPARAM("/" IMPLNAME2 "/UNO/SERVICES") ) ) ); + + const Sequence< OUString > & rSNL = + ::excomp2_impl::ExampleComponent2Impl::getSupportedServiceNames_Static(); + const OUString * pArray = rSNL.getConstArray(); + for ( sal_Int32 nPos = rSNL.getLength(); nPos--; ) + xNewKey->createKey( pArray[nPos] ); + + return sal_True; + } + catch (InvalidRegistryException &) + { + OSL_ENSURE( sal_False, "### InvalidRegistryException!" ); + } + } + return sal_False; +} +//================================================================================================== +void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * /* pRegistryKey */ ) +{ + void * pRet = 0; + + if (rtl_str_compare( pImplName, IMPLNAME2 ) == 0) + { + Reference< XSingleServiceFactory > xFactory( createSingleFactory( + reinterpret_cast< XMultiServiceFactory * >( pServiceManager ), + OUString( RTL_CONSTASCII_USTRINGPARAM(IMPLNAME2) ), + ::excomp2_impl::ExampleComponent2_CreateInstance, + ::excomp2_impl::ExampleComponent2Impl::getSupportedServiceNames_Static() ) ); + + if (xFactory.is()) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } + + return pRet; +} +} + + + diff --git a/stoc/test/excomp/excomp2.xml b/stoc/test/excomp/excomp2.xml new file mode 100644 index 000000000000..67df74bd188d --- /dev/null +++ b/stoc/test/excomp/excomp2.xml @@ -0,0 +1,33 @@ +<?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> excomp2 </module-name> + <component-description> + <author> Juergen Schmidt </author> + <name> example.ExampleComponent2.Impl </name> + <description> + This component provides a simple demo component. +</description> + <loader-name> com.sun.star.loader.SharedLibrary </loader-name> + <language> c++ </language> + <status value="final"/> + <supported-service> example.ExampleComponent2 </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.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> example.XTest </type> + </component-description> + <project-build-dependency> cppuhelper </project-build-dependency> + <project-build-dependency> cppu </project-build-dependency> + <project-build-dependency> vos </project-build-dependency> + <project-build-dependency> sal </project-build-dependency> + <runtime-module-dependency> cppuhelper </runtime-module-dependency> + <runtime-module-dependency> cppu </runtime-module-dependency> + <runtime-module-dependency> vos </runtime-module-dependency> + <runtime-module-dependency> sal </runtime-module-dependency> +</module-description> diff --git a/stoc/test/excomp/exports.dxp b/stoc/test/excomp/exports.dxp new file mode 100644 index 000000000000..9630d7e06768 --- /dev/null +++ b/stoc/test/excomp/exports.dxp @@ -0,0 +1,3 @@ +component_getImplementationEnvironment +component_writeInfo +component_getFactory diff --git a/stoc/test/excomp/makefile.mk b/stoc/test/excomp/makefile.mk new file mode 100644 index 000000000000..b41acb372620 --- /dev/null +++ b/stoc/test/excomp/makefile.mk @@ -0,0 +1,130 @@ +#************************************************************************* +# +# 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= excomp +TARGET1= excomp1 +TARGET2= excomp2 +TARGETTYPE=CUI +#LIBTARGET=NO +ENABLE_EXCEPTIONS=TRUE +USE_DEFFILE= TRUE +NO_BSYMBOLIC= TRUE +COMP1TYPELIST=$(TARGET1) +COMP2TYPELIST=$(TARGET2) + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# ------------------------------------------------------------------ + +UNOUCRDEP= $(BIN)$/excomp.rdb +UNOUCRRDB= $(BIN)$/excomp.rdb +UNOUCROUT= $(OUT)$/inc +INCPRE+= $(OUT)$/inc + +UNOTYPES=$($(TARGET1)_XML2CMPTYPES) +UNOTYPES+=$($(TARGET2)_XML2CMPTYPES) +UNOTYPES+= com.sun.star.registry.XImplementationRegistration \ + com.sun.star.lang.XComponent + +# --- Application excomp ------------------------------------------------ +APP1TARGET= $(TARGET) +APP1OBJS= $(OBJ)$/excomp.obj + +APP1STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALHELPERLIB) \ + $(SALLIB) + +# ---- objects ---- +SLOFILES= \ + $(SLO)$/excomp1.obj \ + $(SLO)$/$(COMP1TYPELIST)_description.obj \ + $(SLO)$/excomp2.obj \ + $(SLO)$/$(COMP2TYPELIST)_description.obj + +# ---- excomp1 ------ +SHL1TARGET= $(TARGET1) + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALHELPERLIB) \ + $(SALLIB) + +SHL1DEPN= +SHL1LIBS= +SHL1OBJS= $(SLO)$/excomp1.obj \ + $(SLO)$/$(COMP1TYPELIST)_description.obj +SHL1IMPLIB= i$(TARGET1) +SHL1DEF= $(MISC)$/$(SHL1TARGET).def + +DEF1NAME= $(SHL1TARGET) +DEF1EXPORTFILE= exports.dxp + +# ---- excomp2 ------ +SHL2TARGET= $(TARGET2) + +SHL2STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALHELPERLIB) \ + $(SALLIB) + +SHL2DEPN= +SHL2LIBS= +SHL2OBJS= $(SLO)$/excomp2.obj \ + $(SLO)$/$(COMP2TYPELIST)_description.obj +SHL2IMPLIB= i$(TARGET2) +SHL2DEF= $(MISC)$/$(SHL2TARGET).def + +DEF2NAME= $(SHL2TARGET) +DEF2EXPORTFILE= exports.dxp + +ALLIDLFILES:= example$/XTest.idl example$/ExampleComponent1.idl example$/ExampleComponent2.idl + +# --- Targets ------------------------------------------------------ + +.IF "$(depend)" == "" +ALL : $(BIN)$/excomp.rdb \ + ALLTAR +.ELSE +ALL: ALLDEP +.ENDIF + +.INCLUDE : target.mk + +$(BIN)$/excomp.rdb: $(ALLIDLFILES) + idlc -I$(PRJ) -I$(SOLARIDLDIR) -O$(MISC)$/excomp $? + regmerge $@ /UCR $(MISC)$/excomp$/{$(?:f:s/.idl/.urd/)} + regmerge $@ / $(SOLARBINDIR)$/udkapi.rdb + touch $@ + diff --git a/stoc/test/javavm/jvm_interaction/interactionhandler.cxx b/stoc/test/javavm/jvm_interaction/interactionhandler.cxx new file mode 100644 index 000000000000..076a2e9c1e62 --- /dev/null +++ b/stoc/test/javavm/jvm_interaction/interactionhandler.cxx @@ -0,0 +1,205 @@ +/************************************************************************* + * + * 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 <jni.h> + +//#include <iostream> +#include <stdio.h> +#include <sal/main.h> +#include <rtl/process.h> + +#include <cppuhelper/servicefactory.hxx> +#include <cppuhelper/weak.hxx> +#include <cppuhelper/bootstrap.hxx> +#include <osl/thread.h> + +#include <com/sun/star/registry/XSimpleRegistry.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <com/sun/star/java/XJavaVM.hpp> +#include <com/sun/star/registry/XImplementationRegistration.hpp> +#include <com/sun/star/java/XJavaThreadRegister_11.hpp> + +#include <com/sun/star/uno/XCurrentContext.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <com/sun/star/task/XInteractionRequest.hpp> +#include <com/sun/star/task/XInteractionContinuation.hpp> +#include <com/sun/star/task/XInteractionAbort.hpp> +#include <com/sun/star/task/XInteractionRetry.hpp> +#include <com/sun/star/java/JavaNotConfiguredException.hpp> +#include <com/sun/star/java/MissingJavaRuntimeException.hpp> +#include <com/sun/star/java/JavaDisabledException.hpp> +#include <com/sun/star/java/JavaVMCreationFailureException.hpp> +#include <cppuhelper/implbase1.hxx> +#include <uno/current_context.hxx> +using namespace std; +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::lang; +using namespace com::sun::star::registry; +using namespace com::sun::star::java; +using namespace com::sun::star::task; + +#define OUSTR( x ) OUString(RTL_CONSTASCII_USTRINGPARAM( x )) +#define INTERACTION_HANDLER_NAME "java-vm.interaction-handler" + +class Context: public WeakImplHelper1<XCurrentContext> +{ + virtual Any SAL_CALL getValueByName( const OUString& Name ) throw (RuntimeException); +}; + +class InteractionHandler: public WeakImplHelper1<XInteractionHandler> +{ + virtual void SAL_CALL handle( const Reference< XInteractionRequest >& Request ) + throw (RuntimeException); +}; + +Any SAL_CALL Context::getValueByName( const OUString& Name) throw (RuntimeException) +{ + Any retVal; + if( Name.equals( OUSTR(INTERACTION_HANDLER_NAME))) + { + Reference<XInteractionHandler> handler( static_cast<XWeak*>(new InteractionHandler()), + UNO_QUERY); + retVal <<= handler; + } + return retVal; +} + +void SAL_CALL InteractionHandler::handle( const Reference< XInteractionRequest >& Request ) + throw (RuntimeException) +{ + Any anyExc= Request->getRequest(); + Sequence<Reference< XInteractionContinuation> >seqCont= Request->getContinuations(); + + Reference<XInteractionAbort> abort; + Reference<XInteractionRetry> retry; + + for (sal_Int32 i= 0; i < seqCont.getLength(); i++) + { + abort= Reference<XInteractionAbort>::query( seqCont[i]); + if(abort.is()) + break; + } + for (sal_Int32 i= 0; i < seqCont.getLength(); i++) + { + retry= Reference<XInteractionRetry>::query( seqCont[i]); + if(retry.is()) + break; + } + +// if( abort.is()) +// abort->select(); + + static int cRetry= 0; + + if( cRetry++ == 5) + { + if( abort.is()) + abort->select(); + return; + } + if( retry.is()) + retry->select(); +} + +sal_Bool test1(const Reference< XMultiServiceFactory > & xMgr ) +{ + sal_Bool retVal= sal_True; + setCurrentContext( Reference<XCurrentContext>( static_cast<XWeak*>(new Context()), UNO_QUERY)); + + OUString sVMService( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.java.JavaVirtualMachine")); + Reference<XInterface> xXInt= xMgr->createInstance(sVMService); + if( ! xXInt.is()) + return sal_False; + Reference<XJavaVM> xVM( xXInt, UNO_QUERY); + if( ! xVM.is()) + return sal_False; + + + sal_Int8 arId[16]; + rtl_getGlobalProcessId((sal_uInt8*) arId); + + Any anyVM; + try + { + anyVM = xVM->getJavaVM( Sequence<sal_Int8>(arId, 16)); + } + catch (JavaNotConfiguredException& e) + { + OString msg= OUStringToOString(e.Message, osl_getThreadTextEncoding()); + printf("JavaNotConfiguredException: %s\n", msg.getStr()); + } + catch (JavaVMCreationFailureException& e) + { + OString msg= OUStringToOString(e.Message, osl_getThreadTextEncoding()); + printf("JavaVMCreationFailureException: %s\n", msg.getStr()); + } + catch (MissingJavaRuntimeException& e) + { + OString msg= OUStringToOString(e.Message, osl_getThreadTextEncoding()); + printf("MissingJavaRuntimeException: %s\n", msg.getStr()); + } + catch (JavaDisabledException& e) + { + OString msg= OUStringToOString(e.Message, osl_getThreadTextEncoding()); + printf("JavaDisabledException: %s\n", msg.getStr()); + } + catch (RuntimeException & e) + { + OString msg= OUStringToOString(e.Message, osl_getThreadTextEncoding()); + printf("###RuntimeException: %s\n", msg.getStr()); + retVal= sal_False; + } + return retVal; +} + +SAL_IMPLEMENT_MAIN() +{ + Reference<XSimpleRegistry> xreg= createSimpleRegistry(); + xreg->open( OUString( RTL_CONSTASCII_USTRINGPARAM("applicat.rdb")), + sal_False, sal_False ); + + Reference< XComponentContext > context= bootstrap_InitialComponentContext(xreg); + Reference<XMultiComponentFactory> fac= context->getServiceManager(); + Reference<XMultiServiceFactory> xMgr( fac, UNO_QUERY); + + sal_Bool bSucc = sal_False; + bSucc= test1(xMgr); + Reference< XComponent > xCompContext( context, UNO_QUERY ); + xCompContext->dispose(); + return (bSucc ? 0 : -1); +} + + diff --git a/stoc/test/javavm/jvm_interaction/makefile.mk b/stoc/test/javavm/jvm_interaction/makefile.mk new file mode 100644 index 000000000000..e2e78f2c13f5 --- /dev/null +++ b/stoc/test/javavm/jvm_interaction/makefile.mk @@ -0,0 +1,81 @@ +#************************************************************************* +# +# 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=..$/..$/.. +TARGET= jvminteraction +PRJNAME= stoc +TARGET6= $(TARGET) +TARGETTYPE= CUI +LIBTARGET= NO +ENABLE_EXCEPTIONS=TRUE +NO_BSYMBOLIC= TRUE + +UNOUCRDEP= $(SOLARBINDIR)$/udkapi.rdb +UNOUCRRDB= $(SOLARBINDIR)$/udkapi.rdb +UNOUCROUT= $(OUT)$/inc$ +INCPRE+= $(OUT)$/inc$ + + + +# --- Settings ----------------------------------------------------- +.INCLUDE : settings.mk + +# --- Application 6 - testjavavm ------------------------------------ + +UNOTYPES= com.sun.star.lang.XMultiComponentFactory \ + com.sun.star.uno.XWeak \ + com.sun.star.java.XJavaVM \ + com.sun.star.java.XJavaThreadRegister_11 \ + com.sun.star.java.JavaNotConfiguredException \ + com.sun.star.java.MissingJavaRuntimeException \ + com.sun.star.java.JavaDisabledException \ + com.sun.star.java.JavaVMCreationFailureException \ + com.sun.star.registry.XSimpleRegistry \ + com.sun.star.lang.XComponent \ + com.sun.star.registry.XImplementationRegistration \ + com.sun.star.lang.XSingleServiceFactory \ + com.sun.star.uno.TypeClass \ + com.sun.star.lang.XMultiServiceFactory \ + com.sun.star.uno.XCurrentContext \ + com.sun.star.task.XInteractionHandler \ + com.sun.star.task.XInteractionRequest \ + com.sun.star.task.XInteractionContinuation \ + com.sun.star.task.XInteractionAbort \ + com.sun.star.task.XInteractionRetry \ + + +APP6TARGET= $(TARGET6) +APP6OBJS = $(OBJ)$/interactionhandler.obj +APP6STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALHELPERLIB) \ + $(SALLIB) + +# --- Target ------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/stoc/test/javavm/makefile.mk b/stoc/test/javavm/makefile.mk new file mode 100644 index 000000000000..7f6190fecc4f --- /dev/null +++ b/stoc/test/javavm/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=..$/.. +TARGET= testjavavm +PRJNAME= stoc +TARGET6= testjavavm +TARGETTYPE= CUI +LIBTARGET= NO +ENABLE_EXCEPTIONS=TRUE +NO_BSYMBOLIC= TRUE + +UNOUCRDEP= $(SOLARBINDIR)$/udkapi.rdb +UNOUCRRDB= $(SOLARBINDIR)$/udkapi.rdb +#UNOUCROUT= $(OUT)$/inc$/test +UNOUCROUT= $(OUT)$/inc$ +#INCPRE+= $(OUT)$/inc$/test +INCPRE+= $(OUT)$/inc$ + + + +# --- Settings ----------------------------------------------------- +.INCLUDE : settings.mk + +# --- Application 6 - testjavavm ------------------------------------ + +UNOTYPES= com.sun.star.lang.XMultiComponentFactory \ + com.sun.star.uno.XWeak \ + com.sun.star.java.XJavaVM \ + com.sun.star.java.XJavaThreadRegister_11 \ + com.sun.star.registry.XSimpleRegistry \ + com.sun.star.lang.XComponent \ + com.sun.star.registry.XImplementationRegistration \ + com.sun.star.lang.XSingleServiceFactory \ + com.sun.star.uno.TypeClass \ + com.sun.star.lang.XMultiServiceFactory + +APP6TARGET= $(TARGET6) +APP6OBJS = $(OBJ)$/testjavavm.obj +APP6STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALHELPERLIB) \ + $(SALLIB) +# $(UNOLIB) + +# --- Target ------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/stoc/test/javavm/testapplet/TestApplet.html b/stoc/test/javavm/testapplet/TestApplet.html new file mode 100644 index 000000000000..e83d2ffe7d42 --- /dev/null +++ b/stoc/test/javavm/testapplet/TestApplet.html @@ -0,0 +1,19 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> +<HTML> +<HEAD> + <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=windows-1252"> + <TITLE>A Clock (1.1)</TITLE> + <META NAME="GENERATOR" CONTENT="StarOffice 6.0 (Win32)"> + <META NAME="CREATED" CONTENT="20011119;12262427"> + <META NAME="CHANGED" CONTENT="16010101;0"> +</HEAD> +<BODY LANG="de-DE"> +<H1>TestApplet</H1> +<HR> +<P> +<APPLET CODE="TestApplet.class" ALIGN=BOTTOM WIDTH=170 HEIGHT=150> +</APPLET> +</P> + +</BODY> +</HTML>
\ No newline at end of file diff --git a/stoc/test/javavm/testapplet/TestApplet.java b/stoc/test/javavm/testapplet/TestApplet.java new file mode 100644 index 000000000000..55916cff784b --- /dev/null +++ b/stoc/test/javavm/testapplet/TestApplet.java @@ -0,0 +1,58 @@ +import java.awt.Graphics; +import java.awt.Color; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.io.InputStream; +import java.net.MalformedURLException; +/* + * TestApplet.java + * + * Created on 21. November 2001, 09:37 + */ + +/** + * + * @author jl97489 + * @version + */ +public class TestApplet extends java.applet.Applet { + + /** Initialization method that will be called after the applet is loaded + * into the browser. + */ + public void init () { + setBackground( Color.green); + resize( 300, 300); + + // Security tests. + File f= new File("d:\\temp\\javasecurity.txt"); + SecurityManager mgr= System.getSecurityManager(); + try { + f.createNewFile(); + + // local connection + URL url= new URL("http://localhost:8080/index.html"); + InputStream is= url.openStream(); + // remote connection + url= new URL("http://www.w3.org/index.html"); + is= url.openStream(); + }catch( MalformedURLException mue) { + }catch( IOException e) { + String s= e.getMessage(); + System.out.println(s); + }catch( SandboxSecurityException sse) { + String s= sse.getMessage(); + System.out.println("s"); + } + // catch( Exception ex) { +// String s= ex.getMessage(); +// ex.printStackTrace(); +// } + + } + + public void paint( Graphics g) { + super.paint( g); + } +} diff --git a/stoc/test/javavm/testapplet/makefile.mk b/stoc/test/javavm/testapplet/makefile.mk new file mode 100644 index 000000000000..4ddadebd9aa2 --- /dev/null +++ b/stoc/test/javavm/testapplet/makefile.mk @@ -0,0 +1,55 @@ +#************************************************************************* +# +# 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 = testapplet +PACKAGE = +TARGET = TestApplet + + +# --- Settings ----------------------------------------------------- +#.INCLUDE : $(PRJ)$/util$/makefile.pmk +.INCLUDE : settings.mk +# Files -------------------------------------------------------- +JARFILES = ridl.jar jurt.jar unoil.jar + +JAVAFILES= $(subst,$(CLASSDIR)$/$(PACKAGE)$/, $(subst,.class,.java $(JAVACLASSFILES))) + + +JAVACLASSFILES= \ + $(CLASSDIR)$/$(PACKAGE)$/TestApplet.class + +JARCLASSDIRS= . +#JARTARGET = $(TARGET).jar +#JARCOMPRESS= TRUE +#CUSTOMMANIFESTFILE= .$/manifest + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/stoc/test/javavm/testcomponent/TestComponent.java b/stoc/test/javavm/testcomponent/TestComponent.java new file mode 100644 index 000000000000..5622ba087d7a --- /dev/null +++ b/stoc/test/javavm/testcomponent/TestComponent.java @@ -0,0 +1,128 @@ +import com.sun.star.comp.loader.FactoryHelper; +import com.sun.star.lang.*; +import com.sun.star.uno.*; +import com.sun.star.registry.XRegistryKey; +import java.io.*; +import java.net.*; +//import com.sun.star.lib.sandbox.*; + + +/** This component implements XTypeProvider for use with StarBasic. + * The XServiceInfo is implemented to have an interface in which we can put some + * code just for the sake of debugging. + * + * To debug with JPDA (jdk 1.3), put these lines in the java.ini within the [Java] section: + * -Xdebug + * -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y + * + * When the Virtual Machine service is instantiated it will block until the debugger + * attaches to it on port 8000. You can chose a different port. You attach to the VM using + * jdb by + * + * jdb -connect com.sun.jdi.SocketAttach:hostname=myhost,port=8000 + * + * myhost is the hostname where the VM is running. +*/ +public class TestComponent implements XServiceInfo, XTypeProvider +{ + public static final String __serviceName="JavaTestComponent"; + + // XTypeProvider + public com.sun.star.uno.Type[] getTypes( ) + { + Type[] retValue= new Type[2]; + retValue[0]= new Type( XServiceInfo.class); + retValue[1]= new Type( XTypeProvider.class); + return retValue; + } + // XTypeProvider + public byte[] getImplementationId( ) + { + return TestComponent.class.getName().getBytes(); + } + + + // XServiceName + public String getImplementationName( ) + { + String a= "the functions are for debugging"; + int abc= 34; + String prop= System.getProperty("ftp.proxyHost"); + prop= System.getProperty("ftp.proxyPort"); + prop= System.getProperty("http.proxyHost"); + prop= System.getProperty("http.proxyPort"); + prop= System.getProperty("ftp.nonProxyHosts"); + prop= System.getProperty("http.nonProxyHosts"); + prop= System.getProperty("socksProxyHost"); + prop= System.getProperty("socksProxyPort"); + + prop= System.getProperty("stardiv.security.disableSecurity"); + prop= System.getProperty("appletviewer.security.mode"); + + // Test security settings + File f= new File("c:/temp/javasecurity.txt"); + try { + f.createNewFile(); + + // local connection + URL url= new URL("http://localhost:8080/index.html"); + InputStream is= url.openStream(); + // remote connection + url= new URL("http://www.w3.org/index.html"); + is= url.openStream(); + }catch( MalformedURLException mue) { + }catch( IOException e) { + String s= e.getMessage(); + System.out.println(s); + }/*catch( SandboxSecurityException sse) { + String s= sse.getMessage(); + System.out.println("s"); + } +*/ + + return __serviceName; + } + // XServiceName + public boolean supportsService( /*IN*/String ServiceName ) + { + + return false; + } + + //XServiceName + public String[] getSupportedServiceNames( ) + { + String[] retValue= new String[0]; + return retValue; + } + + public static XSingleServiceFactory __getServiceFactory(String implName, + XMultiServiceFactory multiFactory, + XRegistryKey regKey) + { + XSingleServiceFactory xSingleServiceFactory = null; + + if (implName.equals( TestComponent.class.getName()) ) + xSingleServiceFactory = FactoryHelper.getServiceFactory( TestComponent.class, + TestComponent.__serviceName, + multiFactory, + regKey); + + return xSingleServiceFactory; + } + + /** + * Writes the service information into the given registry key. + * This method is called by the <code>JavaLoader</code> + * <p> + * @return returns true if the operation succeeded + * @param regKey the registryKey + * @see com.sun.star.comp.loader.JavaLoader + */ + public static boolean __writeRegistryServiceInfo(XRegistryKey regKey) + { + return FactoryHelper.writeRegistryServiceInfo( TestComponent.class.getName(), + TestComponent.__serviceName, regKey); + } + +} diff --git a/stoc/test/javavm/testcomponent/makefile.mk b/stoc/test/javavm/testcomponent/makefile.mk new file mode 100644 index 000000000000..a2f8eb16fe4d --- /dev/null +++ b/stoc/test/javavm/testcomponent/makefile.mk @@ -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. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME = testcomponent +PACKAGE = +TARGET = JavaTestComponent + + +# --- Settings ----------------------------------------------------- +#.INCLUDE : $(PRJ)$/util$/makefile.pmk +.INCLUDE : settings.mk +# Files -------------------------------------------------------- +JARFILES = ridl.jar jurt.jar unoil.jar + +CUSTOMMANIFESTFILE= manifest + +JARTARGET = $(TARGET).jar + +JAVAFILES= \ + TestComponent.java + + +JAVACLASSFILES = $(foreach,i,$(JAVAFILES) $(CLASSDIR)$/$(PACKAGE)$/$(i:b).class) + + + + + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/stoc/test/javavm/testcomponent/manifest b/stoc/test/javavm/testcomponent/manifest new file mode 100644 index 000000000000..1763d7bb95f7 --- /dev/null +++ b/stoc/test/javavm/testcomponent/manifest @@ -0,0 +1 @@ +RegistrationClassName: TestComponent diff --git a/stoc/test/javavm/testjavavm.cxx b/stoc/test/javavm/testjavavm.cxx new file mode 100644 index 000000000000..e9111bd3cd1d --- /dev/null +++ b/stoc/test/javavm/testjavavm.cxx @@ -0,0 +1,202 @@ +/************************************************************************* + * + * 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 <jni.h> + +//#include <iostream> +#include <stdio.h> +#include <sal/main.h> +#include <rtl/process.h> + +#include <cppuhelper/servicefactory.hxx> +#include <cppuhelper/weak.hxx> +#include <cppuhelper/bootstrap.hxx> + +#include <com/sun/star/registry/XSimpleRegistry.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XMultiComponentFactory.hpp> +#include <com/sun/star/java/XJavaVM.hpp> +#include <com/sun/star/registry/XImplementationRegistration.hpp> +#include <com/sun/star/java/XJavaThreadRegister_11.hpp> + +//#include <cppuhelper/implbase1.hxx> + +using namespace std; +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::lang; +using namespace com::sun::star::registry; +using namespace com::sun::star::java; + + +sal_Bool testJavaVM(const Reference< XMultiServiceFactory > & xMgr ) +{ + + OUString sVMService( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.java.JavaVirtualMachine")); + Reference<XInterface> xXInt= xMgr->createInstance(sVMService); + if( ! xXInt.is()) + return sal_False; + Reference<XJavaVM> xVM( xXInt, UNO_QUERY); + if( ! xVM.is()) + return sal_False; + Reference<XJavaThreadRegister_11> xreg11(xVM, UNO_QUERY); + if( ! xreg11.is()) + return sal_False; + + + sal_Int8 arId[16]; + rtl_getGlobalProcessId((sal_uInt8*) arId); + Any anyVM = xVM->getJavaVM( Sequence<sal_Int8>(arId, 16)); + if ( ! anyVM.hasValue()) + { + OSL_ENSURE(0,"could not get Java VM"); + return sal_False; + } + + sal_Bool b= xreg11->isThreadAttached(); + xreg11->registerThread(); + b= xreg11->isThreadAttached(); + xreg11->revokeThread(); + b= xreg11->isThreadAttached(); + + + b= xVM->isVMEnabled(); + b= xVM->isVMStarted(); + + + b= xVM->isVMEnabled(); + b= xVM->isVMStarted(); + + + JavaVM* _jvm= *(JavaVM**) anyVM.getValue(); + JNIEnv *p_env; + if( _jvm->AttachCurrentThread((void**) &p_env, 0)) + return sal_False; + +// jclass aJProg = p_env->FindClass("TestJavaVM"); +// if( p_env->ExceptionOccurred()){ +// p_env->ExceptionDescribe(); +// p_env->ExceptionClear(); +// } +// +// jmethodID mid= p_env->GetStaticMethodID( aJProg,"main", "([Ljava/lang/String;)V"); + + jclass cls = p_env->FindClass( "TestJavaVM"); + if (cls == 0) { + OSL_TRACE( "Can't find Prog class\n"); + exit(1); + } + +// jmethodID methid = p_env->GetStaticMethodID( cls, "main", "([Ljava/lang/String;)V"); +// if (methid == 0) { +// OSL_TRACE("Can't find Prog.main\n"); +// exit(1); +// } + +// jstring jstr = p_env->NewStringUTF(" from C!"); +// if (jstr == 0) { +// OSL_TRACE("Out of memory\n"); +// exit(1); +// } +// jobjectArray args = p_env->NewObjectArray( 1, +// p_env->FindClass("java/lang/String"), jstr); +// if (args == 0) { +// OSL_TRACE( "Out of memory\n"); +// exit(1); +// } +// p_env->CallStaticVoidMethod( cls, methid, args); + + + jmethodID id = p_env->GetStaticMethodID( cls, "getInt", "()I"); + if( id) + { +// jint _i= p_env->CallStaticIntMethod(cls, id); + p_env->CallStaticIntMethod(cls, id); + } + + if( p_env->ExceptionOccurred()){ + p_env->ExceptionDescribe(); + p_env->ExceptionClear(); + } + + + _jvm->DetachCurrentThread(); + return sal_True; +} + +SAL_IMPLEMENT_MAIN() +{ + Reference<XSimpleRegistry> xreg= createSimpleRegistry(); + xreg->open( OUString( RTL_CONSTASCII_USTRINGPARAM("applicat.rdb")), + sal_False, sal_False ); + + Reference< XComponentContext > context= bootstrap_InitialComponentContext(xreg); + Reference<XMultiComponentFactory> fac= context->getServiceManager(); + Reference<XMultiServiceFactory> xMgr( fac, UNO_QUERY); + + sal_Bool bSucc = sal_False; + try + { + OUString sImplReg(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.ImplementationRegistration")); + Reference<com::sun::star::registry::XImplementationRegistration> xImplReg( + xMgr->createInstance( sImplReg ), UNO_QUERY ); + OSL_ENSURE( xImplReg.is(), "### no impl reg!" ); + + + OUString sLibLoader( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.loader.SharedLibrary")); + OUString sJenLib( + RTL_CONSTASCII_USTRINGPARAM( "javavm.uno" SAL_DLLEXTENSION ) ); + xImplReg->registerImplementation( + sLibLoader, sJenLib, Reference< XSimpleRegistry >() ); + + bSucc = testJavaVM( xMgr ); + } + catch (Exception & rExc) + { + OSL_ENSURE( sal_False, "### exception occured!" ); + OString aMsg( OUStringToOString( rExc.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( "### exception occured: " ); + OSL_TRACE( aMsg.getStr() ); + OSL_TRACE( "\n" ); + } + + Reference< XComponent > xCompContext( context, UNO_QUERY ); + xCompContext->dispose(); + printf("javavm %s", bSucc ? "succeeded" : "failed"); +// cout << "javavm " << (bSucc ? "succeeded" : "failed") << " !" << endl; + return (bSucc ? 0 : -1); +} + + diff --git a/stoc/test/javavm/testjavavm.java b/stoc/test/javavm/testjavavm.java new file mode 100644 index 000000000000..3de93cfc690f --- /dev/null +++ b/stoc/test/javavm/testjavavm.java @@ -0,0 +1,39 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +class TestJavaVM +{ + public static int getInt() + { + return 100; + } + + public static void main( String args[]) + { + System.out.println("Hello World"); + } +} diff --git a/stoc/test/language_binding.idl b/stoc/test/language_binding.idl new file mode 100644 index 000000000000..705ef1c2825a --- /dev/null +++ b/stoc/test/language_binding.idl @@ -0,0 +1,177 @@ +/************************************************************************* + * + * 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 _TEST_LANGUAGE_BINDING_IDL_ +#define _TEST_LANGUAGE_BINDING_IDL_ + +#include <com/sun/star/uno/XInterface.idl> +#include <com/sun/star/lang/IllegalArgumentException.idl> + +module test +{ + +enum TestEnum +{ + TEST, + ONE, + TWO, + CHECK, + LOLA, + PALOO, + ZA +}; + +/** + * simple c++ types + */ +struct TestSimple +{ + boolean Bool; + char Char; + byte Byte; + short Short; + unsigned short UShort; + long Long; + unsigned long ULong; + hyper Hyper; + unsigned hyper UHyper; + float Float; + double Double; + test::TestEnum Enum; +}; +/** + * complex c++ types + */ +struct TestElement : test::TestSimple +{ + string String; + com::sun::star::uno::XInterface Interface; + any Any; +}; +struct TestDataElements : test::TestElement +{ + sequence<test::TestElement > Sequence; +}; + +typedef TestDataElements TestData; + +/** + * Monster test interface to test language binding calls. + * + * @author Daniel Boelzle + */ +interface XLBTestBase : com::sun::star::uno::XInterface +{ + /** + * in parameter test, tests by calls reference also (complex types) + */ + [oneway] void setValues( [in] boolean bBool, [in] char cChar, [in] byte nByte, + [in] short nShort, [in] unsigned short nUShort, + [in] long nLong, [in] unsigned long nULong, + [in] hyper nHyper, [in] unsigned hyper nUHyper, + [in] float fFloat, [in] double fDouble, + [in] test::TestEnum eEnum, [in] string aString, + [in] com::sun::star::uno::XInterface xInterface, [in] any aAny, + [in] sequence<test::TestElement > aSequence, + [in] test::TestData aStruct ); + /** + * inout parameter test + */ + test::TestData setValues2( [inout] boolean bBool, [inout] char cChar, [inout] byte nByte, + [inout] short nShort, [inout] unsigned short nUShort, + [inout] long nLong, [inout] unsigned long nULong, + [inout] hyper nHyper, [inout] unsigned hyper nUHyper, + [inout] float fFloat, [inout] double fDouble, + [inout] test::TestEnum eEnum, [inout] string aString, + [inout] com::sun::star::uno::XInterface xInterface, [inout] any aAny, + [inout] sequence<test::TestElement > aSequence, + [inout] test::TestData aStruct ); + + /** + * out parameter test + */ + test::TestData getValues( [out] boolean bBool, [out] char cChar, [out] byte nByte, + [out] short nShort, [out] unsigned short nUShort, + [out] long nLong, [out] unsigned long nULong, + [out] hyper nHyper, [out] unsigned hyper nUHyper, + [out] float fFloat, [out] double fDouble, + [out] test::TestEnum eEnum, [out] string aString, + [out] com::sun::star::uno::XInterface xInterface, [out] any aAny, + [out] sequence<test::TestElement > aSequence, + [out] test::TestData aStruct ); + + [attribute] boolean Bool; + [attribute] byte Byte; + [attribute] char Char; + [attribute] short Short; + [attribute] unsigned short UShort; + [attribute] long Long; + [attribute] unsigned long ULong; + [attribute] hyper Hyper; + [attribute] unsigned hyper UHyper; + [attribute] float Float; + [attribute] double Double; + [attribute] test::TestEnum Enum; + [attribute] string String; + [attribute] com::sun::star::uno::XInterface Interface; + [attribute] any Any; + [attribute] sequence<test::TestElement > Sequence; + [attribute] test::TestData Struct; +}; + + +/** + * Inherting from monster; adds raiseException(). + * + * @author Daniel Boelzle + */ +interface XLanguageBindingTest : test::XLBTestBase +{ + /** + * params are there only for dummy, to test if all temp out params will be released. + */ + test::TestData raiseException( [out] boolean bBool, [out] char cChar, [out] byte nByte, + [out] short nShort, [out] unsigned short nUShort, + [out] long nLong, [out] unsigned long nULong, + [out] hyper nHyper, [out] unsigned hyper nUHyper, + [out] float fFloat, [out] double fDouble, + [out] test::TestEnum eEnum, [out] string aString, + [out] com::sun::star::uno::XInterface xInterface, [out] any aAny, + [out] sequence<test::TestElement > aSequence, + [out] test::TestData aStruct ) + raises( com::sun::star::lang::IllegalArgumentException ); + + /** + * raises runtime exception + */ + [attribute] long RuntimeException; +}; + +}; // test + + +#endif diff --git a/stoc/test/makefile.mk b/stoc/test/makefile.mk new file mode 100644 index 000000000000..a7b18d062f8b --- /dev/null +++ b/stoc/test/makefile.mk @@ -0,0 +1,223 @@ +#************************************************************************* +# +# 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=stoc +TARGET1=testloader +TARGET2=testregistry +TARGET3=testsmgr +TARGET4=testcorefl +TARGET5=testinvocation +TARGET6=testintrosp +TARGET7=testconv +TARGET8=testproxyfac +TARGET9=testsmgr2 +TARGETTYPE=CUI +#LIBTARGET=NO +ENABLE_EXCEPTIONS=TRUE +NO_BSYMBOLIC=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- smgr component ----------------------------------------------- +SHL1OBJS= \ + $(OBJ)$/testsmgr_cpnt.obj + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALHELPERLIB) \ + $(SALLIB) + +SHL1TARGET=testsmgr_component +SHL1DEPN= +SHL1IMPLIB=i$(SHL1TARGET) +#SHL1LIBS=$(SLB)$/$(SHL1TARGET).lib +SHL1DEF=$(MISC)$/$(SHL1TARGET).def +DEF1NAME=$(SHL1TARGET) +SHL1VERSIONMAP=testsmgr_cpnt.map + +# --- Application 1 ------------------------------------------------ +APP1TARGET= $(TARGET1) +APP1OBJS= $(OBJ)$/testloader.obj + +APP1STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALHELPERLIB) \ + $(SALLIB) + +# --- Application 2 ------------------------------------------------ +APP2TARGET= $(TARGET2) +APP2OBJS= $(OBJ)$/testregistry.obj $(OBJ)$/mergekeys_.obj + +APP2STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALHELPERLIB) \ + $(REGLIB) \ + $(SALLIB) + +# --- Application 3 - testsmgr main ------------------------------------ +APP3TARGET= $(TARGET3) +APP3OBJS = $(OBJ)$/testsmgr.obj +APP3STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALHELPERLIB) \ + $(REGLIB) \ + $(SALLIB) + +.IF "$(GUI)"=="UNX" +APP3STDLIBS+= -l$(SHL1TARGET) +.ENDIF +.IF "$(GUI)"=="WNT" || "$(GUI)"=="OS2" +APP3STDLIBS+= i$(SHL1TARGET).lib +.ENDIF + +# --- Application 4 - testcorefl main ------------------------------------ +APP4TARGET= $(TARGET4) +APP4OBJS = $(OBJ)$/testcorefl.obj +APP4STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) + +# --- Application 5 - testinvocation main ------------------------------------ +APP5TARGET= $(TARGET5) +APP5OBJS = $(OBJ)$/testiadapter.obj +APP5STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) + +# --- Application 6 - testitrosp main ------------------------------------ +APP6TARGET= $(TARGET6) +APP6OBJS = $(OBJ)$/testintrosp.obj +APP6STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALHELPERLIB) \ + $(SALLIB) + +# --- Application 7 - testconv main ------------------------------------ +APP7TARGET= $(TARGET7) +APP7OBJS = $(OBJ)$/testconv.obj +APP7STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) + +# --- Application 8 - testproxyfac main ------------------------------------ +APP8TARGET= $(TARGET8) +APP8OBJS = $(OBJ)$/testproxyfac.obj +APP8STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) + +# --- Application 9 - testproxyfac main ------------------------------------ +APP9TARGET= $(TARGET9) +APP9OBJS = $(OBJ)$/testsmgr2.obj +APP9STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) + + +ALLIDLFILES:= testcorefl.idl language_binding.idl testintrosp.idl + + +# --- Target ------------------------------------------------ + +.IF "$(depend)" == "" +ALL : $(MISC)$/test_types_generated.flag \ + $(BIN)$/test1.rdb \ + $(BIN)$/test2.rdb \ + ALLTAR +.ELSE +ALL: ALLDEP +.ENDIF + +.INCLUDE : target.mk + +CPPUMAKERFLAGS = +.IF "$(COM)" == "MSC" +CPPUMAKERFLAGS = -L +.ENDIF + +FACTORYTYPES:= -T com.sun.star.lang.XSingleComponentFactory \ + -T com.sun.star.uno.XComponentContext \ + -T com.sun.star.uno.XWeak \ + -T com.sun.star.container.XEnumeration \ + -T com.sun.star.lang.XComponent \ + -T com.sun.star.registry.XSimpleRegistry \ + -T com.sun.star.lang.XInitialization \ + -T com.sun.star.lang.XMultiServiceFactory\ + -T com.sun.star.loader.XImplementationLoader \ + -T com.sun.star.registry.XImplementationRegistration \ + -T com.sun.star.container.XSet \ + -T com.sun.star.lang.XSingleServiceFactory\ + -T com.sun.star.lang.XServiceInfo \ + -T com.sun.star.container.XContentEnumerationAccess \ + -T com.sun.star.container.XEnumeration + +TESTCOREFL:=ModuleC;ModuleC.XInterfaceA;ModuleC.XInterfaceB;ModuleA.XInterface1;com.sun.star.reflection.XIdlReflection;com.sun.star.reflection.XIdlField;com.sun.star.reflection.XIdlArray;com.sun.star.reflection.XIdlMethod;com.sun.star.reflection.XIdlClass;com.sun.star.beans.XPropertySet;com.sun.star.lang.XComponent;com.sun.star.container.XHierarchicalNameAccess;com.sun.star.reflection.XIdlField2;com.sun.star.lang.DisposedException +TESTIADAPTER:=com.sun.star.beans.XIntrospection;com.sun.star.beans.MethodConcept;com.sun.star.beans.XExactName;com.sun.star.lang.XTypeProvider;com.sun.star.uno.XAggregation;com.sun.star.script.XInvocationAdapterFactory;com.sun.star.script.XInvocationAdapterFactory2;com.sun.star.script.XInvocation;com.sun.star.lang.XMultiServiceFactory;com.sun.star.registry.XSimpleRegistry;com.sun.star.lang.XInitialization;test.XLanguageBindingTest +TESTINTROSP:=ModuleA;ModuleA.XIntroTest;com.sun.star.beans.XPropertySet;com.sun.star.container.XIndexAccess;com.sun.star.container.XNameAccess;com.sun.star.beans.PropertyAttribute;com.sun.star.beans.PropertyConcept +TESTCONV:=com.sun.star.script.XTypeConverter +TESTPROXYFAC:=com.sun.star.reflection.XProxyFactory +TESTSECURITY:=com.sun.star.security.AllPermission;com.sun.star.security.XPolicy;com.sun.star.security.XAccessController;com.sun.star.io.FilePermission;com.sun.star.connection.SocketPermission;com.sun.star.uno.XCurrentContext + +$(BIN)$/test1.rdb: $(SHL1TARGETN) +.IF "$(GUI)"=="UNX" + cp $(SHL1TARGETN) $(BIN) +.ENDIF + cd $(BIN) && regcomp -register -r test1.rdb -c $(SHL1TARGET) + +$(BIN)$/test2.rdb: + cd $(BIN) && regcomp -register -r test2.rdb -c remotebridge.uno$(DLLPOST) + +$(BIN)$/stoctest.rdb: $(ALLIDLFILES) + idlc -I$(PRJ) -I$(SOLARIDLDIR) -O$(BIN) $? + regmerge $@ /UCR $(BIN)$/{$(?:f:s/.idl/.urd/)} + regmerge $@ / $(SOLARBINDIR)$/udkapi.rdb + regcomp -register -r $@ -c reflection.uno$(DLLPOST) + touch $@ + +$(MISC)$/test_types_generated.flag : $(BIN)$/stoctest.rdb makefile.mk + -rm -f $(MISC)$/test_types_generated.flag + cppumaker $(CPPUMAKERFLAGS) -BUCR -O$(UNOUCROUT) $(FACTORYTYPES) -T"$(TESTIADAPTER)" $(BIN)$/stoctest.rdb + cppumaker $(CPPUMAKERFLAGS) -BUCR -O$(UNOUCROUT) -T"$(TESTCOREFL)" $(BIN)$/stoctest.rdb + cppumaker $(CPPUMAKERFLAGS) -BUCR -O$(UNOUCROUT) -T"$(TESTINTROSP)" $(BIN)$/stoctest.rdb + cppumaker $(CPPUMAKERFLAGS) -BUCR -O$(UNOUCROUT) -T"$(TESTCONV)" $(BIN)$/stoctest.rdb + cppumaker $(CPPUMAKERFLAGS) -BUCR -O$(UNOUCROUT) -T"$(TESTPROXYFAC)" $(BIN)$/stoctest.rdb + cppumaker $(CPPUMAKERFLAGS) -BUCR -O$(UNOUCROUT) -T"$(TESTSECURITY)" $(BIN)$/stoctest.rdb + touch $(MISC)$/test_types_generated.flag diff --git a/stoc/test/mergekeys_.cxx b/stoc/test/mergekeys_.cxx new file mode 100644 index 000000000000..b75a1ef7df35 --- /dev/null +++ b/stoc/test/mergekeys_.cxx @@ -0,0 +1,31 @@ +/************************************************************************* + * + * 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 "../source/implementationregistration/mergekeys.cxx" diff --git a/stoc/test/registry_tdprovider/makefile.mk b/stoc/test/registry_tdprovider/makefile.mk new file mode 100644 index 000000000000..f258963f9299 --- /dev/null +++ b/stoc/test/registry_tdprovider/makefile.mk @@ -0,0 +1,63 @@ +#************************************************************************* +# +# 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 := test_registry_tdprovider + +ENABLE_EXCEPTIONS := TRUE + +.INCLUDE: settings.mk + +DLLPRE = # no leading "lib" on .so files + +SLOFILES = $(SLO)$/testregistrytdprovider.obj + +SHL1TARGET = testregistrytdprovider.uno +SHL1OBJS = $(SLOFILES) +SHL1VERSIONMAP = $(SOLARENV)/src/component.map +SHL1STDLIBS = $(CPPULIB) $(CPPUHELPERLIB) $(SALLIB) +SHL1IMPLIB = itestregistrytdprovider +DEF1NAME = $(SHL1TARGET) + +.INCLUDE: target.mk + +ALLTAR: test + +$(MISC)$/$(TARGET)$/all.rdb: types.idl + - rm $@ + - $(MKDIR) $(MISC)$/$(TARGET) + idlc -O$(MISC)$/$(TARGET) -I$(SOLARIDLDIR) -C -cid -we $< + regmerge $@ /UCR $(MISC)$/$(TARGET)$/types.urd + regmerge $@ / $(SOLARBINDIR)$/types.rdb + +$(SLOFILES): $(MISC)$/$(TARGET)$/all.rdb + +test .PHONY: $(SHL1TARGETN) $(MISC)$/$(TARGET)$/all.rdb + uno -c test.registrytdprovider.impl -l $(subst,$/,/ $(SHL1TARGETN)) \ + -ro $(subst,$/,/ $(MISC)$/$(TARGET)$/all.rdb) diff --git a/stoc/test/registry_tdprovider/readme.txt b/stoc/test/registry_tdprovider/readme.txt new file mode 100644 index 000000000000..9267df8582f6 --- /dev/null +++ b/stoc/test/registry_tdprovider/readme.txt @@ -0,0 +1,4 @@ +This test uses the delivered regtypeprov.uno dynamic library, not the local one. +(It might work to fix this, changing the test from a UNO component started from +the uno executable to a stand-alone application that bootstraps UNO in a special +way.) diff --git a/stoc/test/registry_tdprovider/testregistrytdprovider.cxx b/stoc/test/registry_tdprovider/testregistrytdprovider.cxx new file mode 100644 index 000000000000..ca245d7d7f43 --- /dev/null +++ b/stoc/test/registry_tdprovider/testregistrytdprovider.cxx @@ -0,0 +1,943 @@ +/************************************************************************* + * + * 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 "com/sun/star/beans/XPropertySet.hpp" +#include "com/sun/star/container/XHierarchicalNameAccess.hpp" +#include "com/sun/star/lang/XMain.hpp" +#include "com/sun/star/lang/XSingleComponentFactory.hpp" +#include "com/sun/star/reflection/XCompoundTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp" +#include "com/sun/star/reflection/XInterfaceMemberTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceTypeDescription2.hpp" +#include "com/sun/star/reflection/XPublished.hpp" +#include "com/sun/star/reflection/XServiceTypeDescription2.hpp" +#include "com/sun/star/reflection/XSingletonTypeDescription2.hpp" +#include "com/sun/star/reflection/XStructTypeDescription.hpp" +#include "com/sun/star/reflection/XTypeDescription.hpp" +#include "com/sun/star/registry/InvalidRegistryException.hpp" +#include "com/sun/star/registry/XRegistryKey.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/TypeClass.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "cppuhelper/factory.hxx" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/weak.hxx" +#include "rtl/textenc.h" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "uno/environment.h" +#include "uno/lbnames.h" + +#include /*MSVC trouble: <cstdlib>*/ <stdlib.h> +#include <iostream> +#include <ostream> + +namespace css = com::sun::star; + +namespace { + +class Service: public cppu::WeakImplHelper1< css::lang::XMain > { +public: + virtual sal_Int32 SAL_CALL + run(css::uno::Sequence< rtl::OUString > const & arguments) + throw (css::uno::RuntimeException); + + static rtl::OUString getImplementationName(); + + static css::uno::Sequence< rtl::OUString > getSupportedServiceNames(); + + static css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance( + css::uno::Reference< css::uno::XComponentContext > const & context) + throw (css::uno::Exception); + +private: + explicit Service( + css::uno::Reference< css::uno::XComponentContext > const & context): + m_context(context) + {} + + css::uno::Reference< css::uno::XComponentContext > m_context; +}; + +} + +namespace { + +std::ostream & operator <<(std::ostream & out, rtl::OUString const & value) { + return out << rtl::OUStringToOString(value, RTL_TEXTENCODING_UTF8).getStr(); +} + +void assertTrue(bool argument) { + if (!argument) { + std::cerr + << "assertTrue(" << argument << ") failed" << std::endl; + /*MSVC trouble: std::*/abort(); + } +} + +void assertFalse(bool argument) { + if (argument) { + std::cerr + << "assertFalse(" << argument << ") failed" << std::endl; + /*MSVC trouble: std::*/abort(); + } +} + +template< typename T > void assertEqual(T const & value, T const & argument) { + if (argument != value) { + std::cerr + << "assertEqual(" << value << ", " << argument << ") failed" + << std::endl; + /*MSVC trouble: std::*/abort(); + } +} + +} + +sal_Int32 Service::run(css::uno::Sequence< rtl::OUString > const &) + throw (css::uno::RuntimeException) +{ + css::uno::Reference< css::lang::XMultiComponentFactory > factory( + m_context->getServiceManager()); + assertTrue(factory.is()); + css::uno::Sequence< css::uno::Any > args(1); + args[0] = css::uno::Reference< css::beans::XPropertySet >( + factory, css::uno::UNO_QUERY_THROW)->getPropertyValue( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Registry"))); + css::uno::Reference< css::container::XHierarchicalNameAccess > provider( + factory->createInstanceWithArgumentsAndContext( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.stoc.RegistryTypeDescriptionProvider")), + args, m_context), + css::uno::UNO_QUERY_THROW); + + // The following assumes that interface members are sorted by increasing + // values of XInterfaceMemberTypeDescription.getPosition, the exceptions + // of interface attributes and interface methods, the constructors of + // services, and the exceptions of service constructors are sorted as given + // in the UNOIDL source code: + + assertEqual< bool >( + false, + provider->hasByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("[][]boolean")))); + assertEqual< bool >( + false, + provider->hasByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Struct3<boolean,boolean>")))); + assertEqual< bool >( + false, + provider->hasByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.uno.XComponentContext::getValueByName")))); + + css::uno::Reference< css::reflection::XCompoundTypeDescription > exception; + exception + = css::uno::Reference< css::reflection::XCompoundTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.Exception"))), + css::uno::UNO_QUERY_THROW); + assertEqual(css::uno::TypeClass_EXCEPTION, exception->getTypeClass()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.Exception")), + exception->getName()); + assertFalse(exception->getBaseType().is()); + exception + = css::uno::Reference< css::reflection::XCompoundTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.uno.RuntimeException"))), + css::uno::UNO_QUERY_THROW); + assertEqual(css::uno::TypeClass_EXCEPTION, exception->getTypeClass()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.RuntimeException")), + exception->getName()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.Exception")), + exception->getBaseType()->getName()); + + css::uno::Reference< css::reflection::XStructTypeDescription > structure; + + structure = css::uno::Reference< css::reflection::XStructTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Struct2"))), + css::uno::UNO_QUERY_THROW); + assertEqual(css::uno::TypeClass_STRUCT, structure->getTypeClass()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.Struct2")), + structure->getName()); + assertFalse(structure->getBaseType().is()); + assertEqual< sal_Int32 >(1, structure->getMemberTypes().getLength()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.Struct1")), + structure->getMemberTypes()[0]->getName()); + assertEqual< sal_Int32 >(1, structure->getMemberNames().getLength()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("s1")), + structure->getMemberNames()[0]); + assertEqual< sal_Int32 >(0, structure->getTypeParameters().getLength()); + assertEqual< sal_Int32 >(0, structure->getTypeArguments().getLength()); + + structure = css::uno::Reference< css::reflection::XStructTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Struct3"))), + css::uno::UNO_QUERY_THROW); + assertEqual(css::uno::TypeClass_STRUCT, structure->getTypeClass()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.Struct3")), + structure->getName()); + assertFalse(structure->getBaseType().is()); + assertEqual< sal_Int32 >(1, structure->getMemberTypes().getLength()); + assertEqual( + css::uno::TypeClass_UNKNOWN, + structure->getMemberTypes()[0]->getTypeClass()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("U")), + structure->getMemberTypes()[0]->getName()); + assertEqual< sal_Int32 >(1, structure->getMemberNames().getLength()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("s2")), + structure->getMemberNames()[0]); + assertEqual< sal_Int32 >(2, structure->getTypeParameters().getLength()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("T")), + structure->getTypeParameters()[0]); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("U")), + structure->getTypeParameters()[1]); + assertEqual< sal_Int32 >(0, structure->getTypeArguments().getLength()); + + structure = css::uno::Reference< css::reflection::XStructTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Struct4"))), + css::uno::UNO_QUERY_THROW); + assertEqual(css::uno::TypeClass_STRUCT, structure->getTypeClass()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.Struct4")), + structure->getName()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.Struct2")), + structure->getBaseType()->getName()); + assertEqual< sal_Int32 >(1, structure->getMemberTypes().getLength()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Struct3<" + "test.registrytdprovider.Struct2," + "test.registrytdprovider.Struct3<boolean,any>>")), + structure->getMemberTypes()[0]->getName()); + assertEqual< sal_Int32 >(1, structure->getMemberNames().getLength()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("s2")), + structure->getMemberNames()[0]); + assertEqual< sal_Int32 >(0, structure->getTypeParameters().getLength()); + assertEqual< sal_Int32 >(0, structure->getTypeArguments().getLength()); + + css::uno::Reference< css::reflection::XInterfaceTypeDescription2 > + interface; + + interface + = css::uno::Reference< css::reflection::XInterfaceTypeDescription2 >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.XTest1"))), + css::uno::UNO_QUERY_THROW); + assertEqual(css::uno::TypeClass_INTERFACE, interface->getTypeClass()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.XTest1")), + interface->getName()); + css::uno::Sequence< + css::uno::Reference< css::reflection::XTypeDescription > > bases( + interface->getBaseTypes()); + assertEqual< sal_Int32 >(1, bases.getLength()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.XInterface")), + bases[0]->getName()); + css::uno::Sequence< + css::uno::Reference< css::reflection::XTypeDescription > > + optionalBases(interface->getOptionalBaseTypes()); + assertEqual< sal_Int32 >(1, optionalBases.getLength()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.XBase")), + optionalBases[0]->getName()); + css::uno::Sequence< + css::uno::Reference< + css::reflection::XInterfaceMemberTypeDescription > > members( + interface->getMembers()); + assertEqual< sal_Int32 >(5, members.getLength()); + + css::uno::Reference< css::reflection::XInterfaceAttributeTypeDescription2 > + attribute; + css::uno::Sequence< + css::uno::Reference< css::reflection::XCompoundTypeDescription > > + getExceptions; + css::uno::Sequence< + css::uno::Reference< css::reflection::XCompoundTypeDescription > > + setExceptions; + css::uno::Reference< css::reflection::XInterfaceMethodTypeDescription > + method; + + attribute = css::uno::Reference< + css::reflection::XInterfaceAttributeTypeDescription2 >( + members[0], css::uno::UNO_QUERY_THROW); + assertEqual( + css::uno::TypeClass_INTERFACE_ATTRIBUTE, attribute->getTypeClass()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.XTest1::a1")), + attribute->getName()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("a1")), + attribute->getMemberName()); + assertEqual< sal_Int32 >(3, attribute->getPosition()); + assertEqual< bool >(false, attribute->isReadOnly()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("short")), + attribute->getType()->getName()); + assertEqual< bool >(true, attribute->isBound()); + getExceptions = attribute->getGetExceptions(); + assertEqual< sal_Int32 >(0, getExceptions.getLength()); + setExceptions = attribute->getSetExceptions(); + assertEqual< sal_Int32 >(0, setExceptions.getLength()); + + attribute = css::uno::Reference< + css::reflection::XInterfaceAttributeTypeDescription2 >( + members[1], css::uno::UNO_QUERY_THROW); + assertEqual( + css::uno::TypeClass_INTERFACE_ATTRIBUTE, attribute->getTypeClass()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.XTest1::a2")), + attribute->getName()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("a2")), + attribute->getMemberName()); + assertEqual< sal_Int32 >(4, attribute->getPosition()); + assertEqual< bool >(false, attribute->isReadOnly()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("long")), + attribute->getType()->getName()); + assertEqual< bool >(false, attribute->isBound()); + getExceptions = attribute->getGetExceptions(); + assertEqual< sal_Int32 >(2, getExceptions.getLength()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.lang.WrappedTargetException")), + getExceptions[0]->getName()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.RuntimeException")), + getExceptions[1]->getName()); + setExceptions = attribute->getSetExceptions(); + assertEqual< sal_Int32 >(2, setExceptions.getLength()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.Exception")), + setExceptions[0]->getName()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.lang.WrappedTargetException")), + setExceptions[1]->getName()); + + attribute = css::uno::Reference< + css::reflection::XInterfaceAttributeTypeDescription2 >( + members[2], css::uno::UNO_QUERY_THROW); + assertEqual( + css::uno::TypeClass_INTERFACE_ATTRIBUTE, attribute->getTypeClass()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.XTest1::a3")), + attribute->getName()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("a3")), + attribute->getMemberName()); + assertEqual< sal_Int32 >(5, attribute->getPosition()); + assertEqual< bool >(true, attribute->isReadOnly()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("hyper")), + attribute->getType()->getName()); + assertEqual< bool >(true, attribute->isBound()); + getExceptions = attribute->getGetExceptions(); + assertEqual< sal_Int32 >(1, getExceptions.getLength()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.lang.WrappedTargetException")), + getExceptions[0]->getName()); + setExceptions = attribute->getSetExceptions(); + assertEqual< sal_Int32 >(0, setExceptions.getLength()); + + method = css::uno::Reference< + css::reflection::XInterfaceMethodTypeDescription >( + members[3], css::uno::UNO_QUERY_THROW); + assertEqual(css::uno::TypeClass_INTERFACE_METHOD, method->getTypeClass()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.XTest1::f1")), + method->getName()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("f1")), + method->getMemberName()); + assertEqual< sal_Int32 >(6, method->getPosition()); + assertEqual< bool >(false, method->isOneway()); + assertEqual< sal_Int32 >(1, method->getParameters().getLength()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("p")), + method->getParameters()[0]->getName()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("any")), + method->getParameters()[0]->getType()->getName()); + assertEqual< bool >(false, method->getParameters()[0]->isIn()); + assertEqual< bool >(true, method->getParameters()[0]->isOut()); + assertEqual< sal_Int32 >(0, method->getParameters()[0]->getPosition()); + assertEqual< sal_Int32 >(1, method->getExceptions().getLength()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.RuntimeException")), + method->getExceptions()[0]->getName()); + + method = css::uno::Reference< + css::reflection::XInterfaceMethodTypeDescription >( + members[4], css::uno::UNO_QUERY_THROW); + assertEqual(css::uno::TypeClass_INTERFACE_METHOD, method->getTypeClass()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.XTest1::f2")), + method->getName()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("f2")), + method->getMemberName()); + assertEqual< sal_Int32 >(7, method->getPosition()); + assertEqual< bool >(true, method->isOneway()); + assertEqual< sal_Int32 >(0, method->getParameters().getLength()); + assertEqual< sal_Int32 >(0, method->getExceptions().getLength()); + + interface + = css::uno::Reference< css::reflection::XInterfaceTypeDescription2 >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.XTest2"))), + css::uno::UNO_QUERY_THROW); + assertEqual(css::uno::TypeClass_INTERFACE, interface->getTypeClass()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.XTest2")), + interface->getName()); + assertEqual< sal_Int32 >(1, interface->getBaseTypes().getLength()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.Typedef2")), + interface->getBaseTypes()[0]->getName()); + assertEqual< sal_Int32 >(0, interface->getOptionalBaseTypes().getLength()); + assertEqual< sal_Int32 >(0, interface->getMembers().getLength()); + + css::uno::Reference< css::reflection::XServiceTypeDescription2 > service; + + service = css::uno::Reference< css::reflection::XServiceTypeDescription2 >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Service1"))), + css::uno::UNO_QUERY_THROW); + assertEqual(css::uno::TypeClass_SERVICE, service->getTypeClass()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.Service1")), + service->getName()); + assertEqual< sal_Int32 >(0, service->getMandatoryServices().getLength()); + assertEqual< sal_Int32 >(0, service->getOptionalServices().getLength()); + assertEqual< sal_Int32 >(0, service->getMandatoryInterfaces().getLength()); + assertEqual< sal_Int32 >(0, service->getOptionalInterfaces().getLength()); + assertEqual< bool >(true, service->isSingleInterfaceBased()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.XTest1")), + service->getInterface()->getName()); + assertEqual< sal_Int32 >(2, service->getConstructors().getLength()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("c1")), + service->getConstructors()[0]->getName()); + assertEqual< sal_Int32 >( + 0, service->getConstructors()[0]->getParameters().getLength()); + assertEqual< sal_Int32 >( + 0, service->getConstructors()[0]->getExceptions().getLength()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("c2")), + service->getConstructors()[1]->getName()); + assertEqual< sal_Int32 >( + 1, service->getConstructors()[1]->getParameters().getLength()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("p")), + service->getConstructors()[1]->getParameters()[0]->getName()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("any")), + (service->getConstructors()[1]->getParameters()[0]->getType()-> + getName())); + assertEqual< bool >( + true, service->getConstructors()[1]->getParameters()[0]->isIn()); + assertEqual< bool >( + false, service->getConstructors()[1]->getParameters()[0]->isOut()); + assertEqual< sal_Int32 >( + 0, service->getConstructors()[1]->getParameters()[0]->getPosition()); + assertEqual< bool >( + true, + service->getConstructors()[1]->getParameters()[0]->isRestParameter()); + assertEqual< sal_Int32 >( + 1, service->getConstructors()[1]->getExceptions().getLength()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.RuntimeException")), + service->getConstructors()[1]->getExceptions()[0]->getName()); + + service = css::uno::Reference< css::reflection::XServiceTypeDescription2 >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Service2"))), + css::uno::UNO_QUERY_THROW); + assertEqual(css::uno::TypeClass_SERVICE, service->getTypeClass()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.Service2")), + service->getName()); + assertEqual< sal_Int32 >(0, service->getMandatoryServices().getLength()); + assertEqual< sal_Int32 >(0, service->getOptionalServices().getLength()); + assertEqual< sal_Int32 >(1, service->getMandatoryInterfaces().getLength()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.XTest1")), + service->getMandatoryInterfaces()[0]->getName()); + assertEqual< sal_Int32 >(1, service->getOptionalInterfaces().getLength()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.XBase")), + service->getOptionalInterfaces()[0]->getName()); + assertEqual< bool >(false, service->isSingleInterfaceBased()); + assertFalse(service->getInterface().is()); + assertEqual< sal_Int32 >(0, service->getConstructors().getLength()); + + service = css::uno::Reference< css::reflection::XServiceTypeDescription2 >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Service3"))), + css::uno::UNO_QUERY_THROW); + assertEqual(css::uno::TypeClass_SERVICE, service->getTypeClass()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.Service3")), + service->getName()); + assertEqual< sal_Int32 >(0, service->getMandatoryServices().getLength()); + assertEqual< sal_Int32 >(0, service->getOptionalServices().getLength()); + assertEqual< sal_Int32 >(0, service->getMandatoryInterfaces().getLength()); + assertEqual< sal_Int32 >(0, service->getOptionalInterfaces().getLength()); + assertEqual< bool >(true, service->isSingleInterfaceBased()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.Typedef2")), + service->getInterface()->getName()); + assertEqual< sal_Int32 >(0, service->getConstructors().getLength()); + + css::uno::Reference< css::reflection::XSingletonTypeDescription2 > + singleton; + + singleton = css::uno::Reference< + css::reflection::XSingletonTypeDescription2 >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Singleton1"))), + css::uno::UNO_QUERY_THROW); + assertEqual(css::uno::TypeClass_SINGLETON, singleton->getTypeClass()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.Singleton1")), + singleton->getName()); + assertFalse(singleton->getService().is()); + assertEqual< bool >(true, singleton->isInterfaceBased()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.XTest1")), + singleton->getInterface()->getName()); + + singleton = css::uno::Reference< + css::reflection::XSingletonTypeDescription2 >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Singleton2"))), + css::uno::UNO_QUERY_THROW); + assertEqual(css::uno::TypeClass_SINGLETON, singleton->getTypeClass()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.Singleton2")), + singleton->getName()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.Service1")), + singleton->getService()->getName()); + assertEqual< bool >(false, singleton->isInterfaceBased()); + assertFalse(singleton->getInterface().is()); + + singleton = css::uno::Reference< + css::reflection::XSingletonTypeDescription2 >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Singleton3"))), + css::uno::UNO_QUERY_THROW); + assertEqual(css::uno::TypeClass_SINGLETON, singleton->getTypeClass()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.Singleton3")), + singleton->getName()); + assertFalse(singleton->getService().is()); + assertEqual< bool >(true, singleton->isInterfaceBased()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider.Typedef2")), + singleton->getInterface()->getName()); + + css::uno::Reference< css::reflection::XPublished > published; + published = css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Enum1"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY); + assertTrue(published.is()); + assertTrue(published->isPublished()); + published = css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Enum2"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY); + assertTrue(published.is()); + assertFalse(published->isPublished()); + published = css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Struct1"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY); + assertTrue(published.is()); + assertTrue(published->isPublished()); + published = css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Struct2"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY); + assertTrue(published.is()); + assertFalse(published->isPublished()); + published = css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Struct3"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY); + assertTrue(published.is()); + assertTrue(published->isPublished()); + published = css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XStructTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Struct3"))), + css::uno::UNO_QUERY_THROW)->getMemberTypes()[0], + css::uno::UNO_QUERY); + assertFalse(published.is()); + published = css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Struct3a"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY); + assertTrue(published.is()); + assertFalse(published->isPublished()); + published = css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Exception1"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY); + assertTrue(published.is()); + assertTrue(published->isPublished()); + published = css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Exception2"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY); + assertTrue(published.is()); + assertFalse(published->isPublished()); + published = css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.XTest1"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY); + assertTrue(published.is()); + assertTrue(published->isPublished()); + published = css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.XTest2"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY); + assertTrue(published.is()); + assertFalse(published->isPublished()); + published = css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Typedef1"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY); + assertTrue(published.is()); + assertTrue(published->isPublished()); + published = css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Typedef2"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY); + assertTrue(published.is()); + assertFalse(published->isPublished()); + //TODO: check constants test.registrytdprovider.Const1 (published), + // test.registrytdprovider.Const2 (unpublished), and + // test.registrytdprovider.Consts1.C (no XPublished), which are not + // accessible via provider->getByHierarchicalName (see #i31428) + published = css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Consts1"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY); + assertTrue(published.is()); + assertTrue(published->isPublished()); + published = css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Consts2"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY); + assertTrue(published.is()); + assertFalse(published->isPublished()); + published = css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("test.registrytdprovider"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY); + assertFalse(published.is()); + published = css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Service1"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY); + assertTrue(published.is()); + assertTrue(published->isPublished()); + published = css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Service2"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY); + assertTrue(published.is()); + assertFalse(published->isPublished()); + published = css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Singleton2"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY); + assertTrue(published.is()); + assertTrue(published->isPublished()); + published = css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + provider->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.registrytdprovider.Singleton1"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY); + assertTrue(published.is()); + assertFalse(published->isPublished()); + + return 0; +} + +rtl::OUString Service::getImplementationName() { + return rtl::OUString::createFromAscii("test.registrytdprovider.impl"); +} + +css::uno::Sequence< rtl::OUString > Service::getSupportedServiceNames() { + return css::uno::Sequence< rtl::OUString >(); +} + +css::uno::Reference< css::uno::XInterface > Service::createInstance( + css::uno::Reference< css::uno::XComponentContext > const & context) + throw (css::uno::Exception) +{ + return static_cast< cppu::OWeakObject * >(new Service(context)); +} + +extern "C" void SAL_CALL component_getImplementationEnvironment( + char const ** envTypeName, uno_Environment **) +{ + if (envTypeName != 0) { + *envTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; + } +} + +extern "C" void * SAL_CALL component_getFactory(char const * implName, + void * serviceManager, void *) { + void * p = 0; + if (serviceManager != 0) { + css::uno::Reference< css::lang::XSingleComponentFactory > f; + if (Service::getImplementationName().equalsAscii(implName)) { + f = cppu::createSingleComponentFactory( + &Service::createInstance, Service::getImplementationName(), + Service::getSupportedServiceNames()); + } + if (f.is()) { + f->acquire(); + p = f.get(); + } + } + return p; +} + +namespace { + +bool writeInfo(void * registryKey, rtl::OUString const & implementationName, + css::uno::Sequence< rtl::OUString > const & serviceNames) { + rtl::OUString keyName(rtl::OUString::createFromAscii("/")); + keyName += implementationName; + keyName += rtl::OUString::createFromAscii("/UNO/SERVICES"); + css::uno::Reference< css::registry::XRegistryKey > key; + try { + key = static_cast< css::registry::XRegistryKey * >(registryKey)-> + createKey(keyName); + } catch (css::registry::InvalidRegistryException &) {} + if (!key.is()) { + return false; + } + bool success = true; + for (sal_Int32 i = 0; i < serviceNames.getLength(); ++i) { + try { + key->createKey(serviceNames[i]); + } catch (css::registry::InvalidRegistryException &) { + success = false; + break; + } + } + return success; +} + +} + +extern "C" sal_Bool SAL_CALL component_writeInfo(void *, void * registryKey) { + return registryKey + && writeInfo(registryKey, Service::getImplementationName(), + Service::getSupportedServiceNames()); +} diff --git a/stoc/test/registry_tdprovider/types.idl b/stoc/test/registry_tdprovider/types.idl new file mode 100644 index 000000000000..636b272226be --- /dev/null +++ b/stoc/test/registry_tdprovider/types.idl @@ -0,0 +1,112 @@ +/************************************************************************* + * + * 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 "com/sun/star/lang/WrappedTargetException.idl" +#include "com/sun/star/uno/Exception.idl" +#include "com/sun/star/uno/RuntimeException.idl" +#include "com/sun/star/uno/XInterface.idl" + +module test { module registrytdprovider { + +published enum Enum1 { E1 }; + +enum Enum2 { E1 }; + +published struct Struct1 { long s1; }; + +struct Struct2 { Struct1 s1; }; + +published struct Struct3<T, U> { U s2; }; + +struct Struct3a<T, U> { U s2; }; + +struct Struct4: Struct2 { Struct3< Struct2, Struct3< boolean, any > > s2; }; + +published exception Exception1: com::sun::star::uno::Exception {}; + +exception Exception2: com::sun::star::uno::Exception {}; + +published interface XBase {}; + +published typedef XBase Typedef1; + +typedef Typedef1 Typedef2; + +published interface XTest1 { + [optional] interface XBase; + + void f1([out] any p) raises (com::sun::star::uno::RuntimeException); + + [oneway] void f2(); + + [attribute, bound] short a1; + + [attribute] long a2 { + get raises + (com::sun::star::lang::WrappedTargetException, + com::sun::star::uno::RuntimeException); + set raises + (com::sun::star::uno::Exception, + com::sun::star::lang::WrappedTargetException); + }; + + [attribute, readonly, bound] hyper a3 { + get raises (com::sun::star::lang::WrappedTargetException); + }; +}; + +interface XTest2: Typedef2 {}; + +published service Service1: XTest1 { + c1(); + + c2([in] any... p) raises (com::sun::star::uno::RuntimeException); +}; + +service Service2 { + [optional] interface XBase; + + interface XTest1; +}; + +service Service3: Typedef2 {}; + +singleton Singleton1: XTest1; + +published singleton Singleton2 { service Service1; }; + +singleton Singleton3: Typedef2; + +published const long Const1 = 0; + +const long Const2 = 0; + +published constants Consts1 { const long C = 0; }; + +constants Consts2 { const long C = 0; }; + +}; }; diff --git a/stoc/test/security/makefile.mk b/stoc/test/security/makefile.mk new file mode 100644 index 000000000000..8acd2c2903d0 --- /dev/null +++ b/stoc/test/security/makefile.mk @@ -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. +# +#************************************************************************* +PRJ=..$/.. + +PRJNAME=stoc +TARGET=test_security +TARGETTYPE=CUI +LIBTARGET=NO +ENABLE_EXCEPTIONS=TRUE +NO_BSYMBOLIC=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Application 1 ------------------------------------------------ +APP1TARGET= $(TARGET) +APP1OBJS= $(OBJ)$/test_security.obj + +APP1STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALHELPERLIB) \ + $(SALLIB) + +.IF "$(GUI)"=="WNT" +APP1STDLIBS+= +# $(LIBCIMT) $(LIBCMT) +.ENDIF + + +# --- Target ------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/stoc/test/security/test_security.cxx b/stoc/test/security/test_security.cxx new file mode 100644 index 000000000000..3678ed2b7c65 --- /dev/null +++ b/stoc/test/security/test_security.cxx @@ -0,0 +1,523 @@ +/************************************************************************* + * + * 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 <stdio.h> + +#include <sal/main.h> +#include <osl/diagnose.h> +#include <osl/socket.hxx> +#include <rtl/string.hxx> +#include <rtl/ustrbuf.hxx> +#include <uno/current_context.hxx> + +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/bootstrap.hxx> +#include <cppuhelper/access_control.hxx> + +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/uno/XCurrentContext.hpp> + +#include <com/sun/star/io/FilePermission.hpp> + +#define USER_CREDS "access-control.user-credentials" +#define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) + + +using namespace ::osl; +using namespace ::rtl; +using namespace ::cppu; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + +//-------------------------------------------------------------------------------------------------- +static OUString localhost( OUString const & addition ) SAL_THROW( () ) +{ + static OUString ip; + if (! ip.getLength()) + { + // dns lookup + SocketAddr addr; + SocketAddr::resolveHostname( OUSTR("localhost"), addr ); + ::oslSocketResult rc = ::osl_getDottedInetAddrOfSocketAddr( addr.getHandle(), &ip.pData ); + if (::osl_Socket_Ok != rc) + fprintf(stdout, "### cannot resolve localhost!" ); + } + OUStringBuffer buf( 48 ); + buf.append( ip ); + buf.append( addition ); + return buf.makeStringAndClear(); +} + +//-------------------------------------------------------------------------------------------------- +static inline void dispose( Reference< XInterface > const & x ) + SAL_THROW( (RuntimeException) ) +{ + Reference< lang::XComponent > xComp( x, UNO_QUERY ); + if (xComp.is()) + { + xComp->dispose(); + } +} +//================================================================================================== +class user_CurrentContext + : public ImplHelper1< XCurrentContext > +{ + oslInterlockedCount m_refcount; + + Reference< XCurrentContext > m_xDelegate; + Any m_userId; + +public: + inline user_CurrentContext( + Reference< XCurrentContext > const & xDelegate, + OUString const & userId ) + SAL_THROW( () ) + : m_refcount( 0 ) + , m_xDelegate( xDelegate ) + , m_userId( makeAny( userId ) ) + {} + + // 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); +}; +//__________________________________________________________________________________________________ +void user_CurrentContext::acquire() + throw () +{ + ::osl_incrementInterlockedCount( &m_refcount ); +} +//__________________________________________________________________________________________________ +void user_CurrentContext::release() + throw () +{ + if (! ::osl_decrementInterlockedCount( &m_refcount )) + { + delete this; + } +} +//__________________________________________________________________________________________________ +Any user_CurrentContext::getValueByName( OUString const & name ) + throw (RuntimeException) +{ + if (name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(USER_CREDS ".id") )) + { + return m_userId; + } + else if (m_xDelegate.is()) + { + return m_xDelegate->getValueByName( name ); + } + else + { + return Any(); + } +} + +// prepends line number +#define CHECK( check, negative_test ) \ +{ \ + try \ + { \ + if (negative_test) \ + { \ + bool thrown = true; \ + try \ + { \ + check; \ + thrown = false; \ + } \ + catch (RuntimeException &) \ + { \ + } \ + if (! thrown) \ + { \ + throw RuntimeException( \ + OUSTR("expected RuntimeException upon check!"), Reference< XInterface >() ); \ + } \ + } \ + else \ + { \ + check; \ + } \ + } \ + catch (RuntimeException & exc) \ + { \ + OUStringBuffer buf( 64 ); \ + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("[line ") ); \ + buf.append( (sal_Int32)__LINE__ ); \ + buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] ") ); \ + buf.append( exc.Message ); \ + throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface >() ); \ + } \ +} + +/* +grant +{ +permission com.sun.star.io.FilePermission "file:///usr/bin/ *", "read"; +permission com.sun.star.io.FilePermission "file:///tmp/-", "read,write"; +permission com.sun.star.io.FilePermission "file:///etc/profile", "read"; + +permission com.sun.star.security.RuntimePermission "DEF"; + +permission com.sun.star.connection.SocketPermission "127.0.0.1:-1023", "resolve, connect, listen"; +permission com.sun.star.connection.SocketPermission "localhost:1024-", "accept, connect, listen, resolve,"; +permission com.sun.star.connection.SocketPermission "*.sun.com:1024-", "resolve"; +}; +*/ +static void check_defaults_pos( AccessControl & ac, bool invert = false ) +{ + // positive tests + CHECK( ac.checkFilePermission( OUSTR("file:///usr/bin/bla"), OUSTR("read") ), invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///tmp/bla"), OUSTR("read,write") ), invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///tmp/path/path/bla"), OUSTR("write") ), invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///etc/profile"), OUSTR("read") ), invert ); + CHECK( ac.checkRuntimePermission( OUSTR("DEF") ), invert ); + CHECK( ac.checkSocketPermission( OUSTR("localhost:1024"), OUSTR("connect") ), invert ); + CHECK( ac.checkSocketPermission( OUSTR("localhost:65535"), OUSTR("resolve") ), invert ); + CHECK( ac.checkSocketPermission( localhost(OUSTR(":2048")), OUSTR("accept,listen") ), invert ); + CHECK( ac.checkSocketPermission( localhost(OUSTR(":1024-")), OUSTR("accept,connect,listen,resolve") ), invert ); + CHECK( ac.checkSocketPermission( OUSTR("localhost:-1023"), OUSTR("resolve,listen,connect") ), invert ); + CHECK( ac.checkSocketPermission( OUSTR("jl-1036.germany.sun.com:1024-"), OUSTR("resolve") ), invert ); +} +static void check_defaults_neg( AccessControl & ac, bool invert = false ) +{ + // negative tests + CHECK( ac.checkFilePermission( OUSTR("file:///usr/tmp"), OUSTR("read") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///"), OUSTR("read") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///usr/bin"), OUSTR("read") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///usr/bin/bla"), OUSTR("write") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///usr/bin/bla"), OUSTR("execute") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///usr/bin/path/bla"), OUSTR("read") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///tmp"), OUSTR("read") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///tmp/"), OUSTR("read") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///tm"), OUSTR("read") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///etc/profile"), OUSTR("write") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///etc/profile/bla"), OUSTR("read") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///etc/blabla"), OUSTR("read,write,execute") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///home/root"), OUSTR("read,write,execute") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///root"), OUSTR("read,write,execute") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///root"), OUSTR("delete") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///root"), OUString() ), !invert ); + CHECK( ac.checkRuntimePermission( OUSTR("ROOT") ), !invert ); + CHECK( ac.checkSocketPermission( OUSTR("localhost:1023"), OUSTR("accept") ), !invert ); + CHECK( ac.checkSocketPermission( OUSTR("localhost:123-"), OUSTR("accept") ), !invert ); + CHECK( ac.checkSocketPermission( localhost(OUSTR(":-1023")), OUSTR("accept") ), !invert ); + CHECK( ac.checkSocketPermission( OUSTR("localhost:-1023"), OUSTR("accept,resolve") ), !invert ); + CHECK( ac.checkSocketPermission( OUSTR("sun.com:1024-"), OUSTR("resolve") ), !invert ); +} + +/* +grant user "dbo" +{ +permission com.sun.star.io.FilePermission "file:///home/dbo/-", "read,write"; +permission com.sun.star.io.FilePermission "-", "read,write"; +permission com.sun.star.io.FilePermission "file:///usr/local/dbo/ *", "read"; + +permission com.sun.star.security.RuntimePermission "DBO"; + +permission com.sun.star.connection.SocketPermission "dbo-1:1024-", "listen"; +permission com.sun.star.connection.SocketPermission "dbo-11081:-1023", "resolve"; +permission com.sun.star.connection.SocketPermission "dbo-11081:18", "listen"; +permission com.sun.star.connection.SocketPermission "dbo-11081:20-24", "listen"; +permission com.sun.star.connection.SocketPermission "dbo-11081", "connect"; +}; +*/ +static void check_dbo_pos( AccessControl & ac, bool invert = false ) +{ + check_defaults_pos( ac, invert ); + // positive tests + CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/bla"), OUSTR("read") ), invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/bla"), OUSTR("write") ), invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/bla"), OUSTR("read,write") ), invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/path/bla"), OUSTR("read,write") ), invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/path/path/bla"), OUSTR("read,write") ), invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///usr/local/dbo/*"), OUSTR("read") ), invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///usr/local/dbo/bla"), OUSTR("read") ), invert ); + CHECK( ac.checkRuntimePermission( OUSTR("DBO") ), invert ); + CHECK( ac.checkSocketPermission( OUSTR("dbo-1:1024-"), OUSTR("listen") ), invert ); + CHECK( ac.checkSocketPermission( OUSTR("dbo-1:2048-3122"), OUSTR("listen") ), invert ); + CHECK( ac.checkSocketPermission( OUSTR("dbo-1:2048-"), OUSTR("listen") ), invert ); + CHECK( ac.checkSocketPermission( OUSTR("dbo-11081:-1023"), OUSTR("resolve") ), invert ); + CHECK( ac.checkSocketPermission( OUSTR("dbo-11081:20-1023"), OUSTR("resolve") ), invert ); + CHECK( ac.checkSocketPermission( OUSTR("dbo-11081:18"), OUSTR("listen") ), invert ); + CHECK( ac.checkSocketPermission( OUSTR("dbo-11081:20-24"), OUSTR("listen") ), invert ); + CHECK( ac.checkSocketPermission( OUSTR("dbo-11081:22"), OUSTR("listen") ), invert ); + CHECK( ac.checkSocketPermission( OUSTR("dbo-11081"), OUSTR("connect") ), invert ); + CHECK( ac.checkSocketPermission( OUSTR("dbo-11081:22"), OUSTR("connect") ), invert ); +} +static void check_dbo_neg( AccessControl & ac, bool invert = false ) +{ + check_defaults_neg( ac, invert ); + // negative tests + CHECK( ac.checkFilePermission( OUSTR("file:///home/-"), OUSTR("read") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///home/jbu/bla"), OUSTR("read") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///home/jbu/bla"), OUSTR("write") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///home/jbu/bla"), OUSTR("read,write") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///home/jbu/path/bla"), OUSTR("read") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/path/path/bla"), OUSTR("read,execute") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///usr/local/-"), OUSTR("read") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///usr/local/dbo/path/bla"), OUSTR("read") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///usr/local/dbo/path/path/bla"), OUSTR("read") ), !invert ); + CHECK( ac.checkRuntimePermission( OUSTR("JBU") ), !invert ); + CHECK( ac.checkSocketPermission( OUSTR("dbo-11081"), OUSTR("listen") ), !invert ); + CHECK( ac.checkSocketPermission( OUSTR("dbo-11081:22"), OUSTR("accept") ), !invert ); + CHECK( ac.checkSocketPermission( OUSTR("jbu-11096:22"), OUSTR("resolve") ), !invert ); +} + +/* +grant user "jbu" +{ +permission com.sun.star.io.FilePermission "file:///home/jbu/-", "read,write"; +permission com.sun.star.io.FilePermission "*", "read,write"; + +permission com.sun.star.security.RuntimePermission "JBU"; + +permission com.sun.star.connection.SocketPermission "jbu-11096","resolve"; +}; +*/ +static void check_jbu_pos( AccessControl & ac, bool invert = false ) +{ + check_defaults_pos( ac, invert ); + // positive tests + CHECK( ac.checkFilePermission( OUSTR("file:///home/jbu/bla"), OUSTR("read") ), invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///home/jbu/bla"), OUSTR("write") ), invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///home/jbu/bla"), OUSTR("read,write") ), invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///home/jbu/path/bla"), OUSTR("read,write") ), invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///home/jbu/path/path/bla"), OUSTR("read,write") ), invert ); + CHECK( ac.checkRuntimePermission( OUSTR("JBU") ), invert ); + CHECK( ac.checkSocketPermission( OUSTR("jbu-11096"), OUSTR("resolve") ), invert ); + CHECK( ac.checkSocketPermission( OUSTR("jbu-11096:20-24"), OUSTR("resolve") ), invert ); + CHECK( ac.checkSocketPermission( OUSTR("dbo-11081.germany.sun.com:2048"), OUSTR("resolve") ), invert ); +} +static void check_jbu_neg( AccessControl & ac, bool invert = false ) +{ + check_defaults_neg( ac, invert ); + // negative tests + CHECK( ac.checkFilePermission( OUSTR("file:///home/-"), OUSTR("read") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/path/bla"), OUSTR("read") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/path/path/bla"), OUSTR("read") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/bla"), OUSTR("read") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/bla"), OUSTR("write") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/bla"), OUSTR("read,write") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///usr/local/-"), OUSTR("read") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///usr/local/dbo/bla"), OUSTR("read") ), !invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///usr/local/dbo/path/path/bla"), OUSTR("read") ), !invert ); + CHECK( ac.checkRuntimePermission( OUSTR("DBO") ), !invert ); + CHECK( ac.checkSocketPermission( OUSTR("jbu-11096:20-24"), OUSTR("accept") ), !invert ); + CHECK( ac.checkSocketPermission( OUSTR("dbo-11081"), OUSTR("connect") ), !invert ); + CHECK( ac.checkSocketPermission( OUSTR("dbo-11081.germany.sun.com"), OUSTR("connect") ), !invert ); +} + +/* +grant principal "root" +{ +permission com.sun.star.security.AllPermission; +}; +*/ +//================================================================================================== +static void check_root_pos( AccessControl & ac, bool invert = false ) +{ + check_defaults_pos( ac, invert ); + check_defaults_neg( ac, !invert ); + check_dbo_pos( ac, invert ); + check_dbo_neg( ac, !invert ); + check_jbu_pos( ac, invert ); + check_jbu_neg( ac, !invert ); + // some more root positive + CHECK( ac.checkFilePermission( OUSTR("file:///etc/blabla"), OUSTR("read,write,execute") ), invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///home/root"), OUSTR("read,write,execute") ), invert ); + CHECK( ac.checkFilePermission( OUSTR("file:///root"), OUSTR("read,write,execute") ), invert ); + CHECK( ac.checkRuntimePermission( OUSTR("ROOT") ), invert ); +} + +//================================================================================================== +class acc_Restr + : public WeakImplHelper1< security::XAccessControlContext > +{ + Any m_perm; + +public: + inline acc_Restr( Any const & perm = Any() ) SAL_THROW( () ) + : m_perm( perm ) + {} + + // XAccessControlContext impl + virtual void SAL_CALL checkPermission( Any const & perm ) + throw (RuntimeException); +}; +//__________________________________________________________________________________________________ +void acc_Restr::checkPermission( Any const & perm ) + throw (RuntimeException) +{ + if (perm != m_perm) + { + throw security::AccessControlException( + OUSTR("dyn violation!"), Reference< XInterface >(), perm ); + } +} + +typedef void (* t_action)( AccessControl &, Any const & arg ); + +//================================================================================================== +class Action + : public WeakImplHelper1< security::XAction > +{ + t_action m_action; + AccessControl & m_ac; + Any m_arg; + +public: + inline Action( t_action action, AccessControl & ac, Any const & arg = Any() ) SAL_THROW( () ) + : m_action( action ) + , m_ac( ac ) + , m_arg( arg ) + {} + + // XAction impl + virtual Any SAL_CALL run() + throw (Exception); +}; +//__________________________________________________________________________________________________ +Any Action::run() + throw (Exception) +{ + (*m_action)( m_ac, m_arg ); + return Any(); +} + +//================================================================================================== +// static void restr_file_permissions( AccessControl & ac ) +// { +// // running in dbo's domain +// /* permission com.sun.star.io.FilePermission "file:///home/dbo/-", ",,read , write "; */ +// CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/bla"), OUSTR("read,write,execute") ), true ); +// CHECK( ac.checkFilePermission( OUSTR("file:///home/dbo/bla"), OUSTR("read,write") ), false ); +// } +//================================================================================================== +static void all_dbo_permissions( AccessControl & ac, Any const & ) +{ + check_dbo_pos( ac ); + check_dbo_neg( ac ); +} +//================================================================================================== +static void no_permissions( AccessControl & ac, Any const & arg ) +{ + check_dbo_pos( ac, true ); + check_dbo_neg( ac ); + // set privs to old dbo restr + Reference< security::XAccessControlContext > xContext; + OSL_VERIFY( arg >>= xContext ); + ac->doPrivileged( + new Action( all_dbo_permissions, ac ), + xContext ); +} +//================================================================================================== +static void check_dbo_dynamic( AccessControl & ac ) +{ + Any arg( makeAny( ac->getContext() ) ); + ac->doRestricted( + new Action( no_permissions, ac, arg ), + new acc_Restr() ); +} + +SAL_IMPLEMENT_MAIN() +{ + try + { + // single-user test + Reference< XComponentContext > xContext( defaultBootstrap_InitialComponentContext( + OUSTR("../../test/security/test_security_singleuser.ini") ) ); + { + ::fprintf( stderr, "[security test] single-user checking dbo..." ); + AccessControl ac( xContext ); + check_dbo_pos( ac ); + check_dbo_neg( ac ); + check_dbo_dynamic( ac ); + ::fprintf( stderr, "dbo checked.\n" ); + } + + // multi-user test + dispose( xContext ); + xContext = defaultBootstrap_InitialComponentContext( + OUSTR("../../test/security/test_security.ini") ); // UNO_AC=on + AccessControl ac( xContext ); + + { + // set up dbo current context + ContextLayer layer( new user_CurrentContext( getCurrentContext(), OUSTR("dbo") ) ); + ::fprintf( stderr, "[security test] multi-user checking dbo..." ); + check_dbo_pos( ac ); + check_dbo_neg( ac ); + check_dbo_dynamic( ac ); + ::fprintf( stderr, "dbo checked.\n" ); + } + { + // set up jbu current context + ContextLayer layer( new user_CurrentContext( getCurrentContext(), OUSTR("jbu") ) ); + ::fprintf( stderr, "[security test] multi-user checking jbu..." ); + check_jbu_pos( ac ); + check_jbu_neg( ac ); + ::fprintf( stderr, "jbu checked.\n" ); + } + { + // set up root current context + ContextLayer layer( new user_CurrentContext( getCurrentContext(), OUSTR("root") ) ); + ::fprintf( stderr, "[security test] multi-user checking root..." ); + check_root_pos( ac ); + ::fprintf( stderr, "root checked.\n" ); + } + { + // set up unknown guest user current context => default permissions + ContextLayer layer( new user_CurrentContext( getCurrentContext(), OUSTR("guest") ) ); + ::fprintf( stderr, "[security test] multi-user checking guest..." ); + check_defaults_pos( ac ); + check_defaults_neg( ac ); + ::fprintf( stderr, "guest checked.\n" ); + } + + dispose( xContext ); + ::fprintf( stderr, "security test succeeded.\n" ); + return 0; + } + catch (Exception & exc) + { + OString str( OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) ); + ::fprintf( stderr, "[security test] error: %s!\n", str.getStr() ); + return 1; + } +} diff --git a/stoc/test/security/test_security.ini b/stoc/test/security/test_security.ini new file mode 100644 index 000000000000..d751bb615164 --- /dev/null +++ b/stoc/test/security/test_security.ini @@ -0,0 +1,6 @@ +UNO_TYPES=stoctest.rdb +UNO_SERVICES=stoctest.rdb +UNO_WRITERDB=stoctest.rdb +UNO_AC=on +UNO_AC_POLICYFILE=../../test/security/test_security.policy +UNO_AC_USERCACHE_SIZE=2 diff --git a/stoc/test/security/test_security.policy b/stoc/test/security/test_security.policy new file mode 100644 index 000000000000..93c2571f7122 --- /dev/null +++ b/stoc/test/security/test_security.policy @@ -0,0 +1,37 @@ +/** dbo + permissions +*/ +grant user "dbo"{ + permission com.sun.star.io.FilePermission "file:///home/dbo/-", ",,read , write "; + permission com.sun.star.io.FilePermission "-", "read ,write"; + permission com.sun.star.connection.SocketPermission "dbo-1:1024-", "listen"; + permission com.sun.star.security.RuntimePermission "DBO"; + permission com.sun.star.connection.SocketPermission "dbo-11081:-1023", "resolve"; + permission com.sun.star.connection.SocketPermission "dbo-11081:18", "listen"; + permission com.sun.star.connection.SocketPermission "dbo-11081:20-24", "listen"; + permission com.sun.star.connection.SocketPermission "dbo-11081", "connect"; + permission com.sun.star.io.FilePermission "file:///usr/local/dbo/*" , "read ";}; +grant user "jbu" { +permission com.sun.star.security.RuntimePermission "JBU"; +permission com.sun.star.io.FilePermission "file:///home/jbu/-" ,"read,write,"; +/*jbu resolve*/permission com.sun.star.connection.SocketPermission "jbu-11096","resolve"; + permission com.sun.star.io.FilePermission "*",",read,write";}; grant user "root"{permission com.sun.star.security.AllPermission;}; + +// granted to anyone + grant +{ + // read out this file + permission com.sun.star.io.FilePermission "../../test/security/test_security.policy", + "read"; + + permission com.sun.star.security.RuntimePermission "DEF"; + permission com.sun.star.io.FilePermission "file:///usr/bin/*", "read"; + permission com.sun.star.io.FilePermission "file:///usr/bin/*", "read"; + permission com.sun.star.io.FilePermission "file:///tmp/-", "read, write"; + permission com.sun.star.io.FilePermission "file:///etc/profile", "read,,"; + permission com.sun.star.connection.SocketPermission "127.0.0.1:-1023", "resolve, connect, listen"; + permission com.sun.star.connection.SocketPermission "localhost:1024-", "accept, connect, listen, resolve,"; + permission com.sun.star.connection.SocketPermission "*.sun.com:1024-", "resolve"; + } ; + +# eof
\ No newline at end of file diff --git a/stoc/test/security/test_security_singleuser.ini b/stoc/test/security/test_security_singleuser.ini new file mode 100644 index 000000000000..243c45d997f5 --- /dev/null +++ b/stoc/test/security/test_security_singleuser.ini @@ -0,0 +1,6 @@ +UNO_TYPES=stoctest.rdb +UNO_SERVICES=stoctest.rdb +UNO_WRITERDB=stoctest.rdb +UNO_AC=single-user +UNO_AC_SINGLEUSER=dbo +UNO_AC_POLICYFILE=../../test/security/test_security.policy diff --git a/stoc/test/tdmanager/makefile.mk b/stoc/test/tdmanager/makefile.mk new file mode 100644 index 000000000000..8f39ac552038 --- /dev/null +++ b/stoc/test/tdmanager/makefile.mk @@ -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. +# +#************************************************************************* + +PRJ := ..$/.. +PRJNAME := stoc + +TARGET := test_tdmanager + +ENABLE_EXCEPTIONS := TRUE + +.INCLUDE: settings.mk + +DLLPRE = # no leading "lib" on .so files + +SLOFILES = $(SLO)$/testtdmanager.obj + +SHL1TARGET = testtdmanager.uno +SHL1OBJS = $(SLOFILES) +SHL1VERSIONMAP = $(SOLARENV)/src/component.map +SHL1STDLIBS = $(CPPULIB) $(CPPUHELPERLIB) $(SALLIB) +SHL1IMPLIB = itesttdmanager +DEF1NAME = $(SHL1TARGET) + +.INCLUDE: target.mk + +ALLTAR: test + +$(MISC)$/$(TARGET)$/%.rdb : %.idl + - rm $@ + - $(MKDIR) $(MISC)$/$(TARGET) + idlc -O$(MISC)$/$(TARGET) -I$(SOLARIDLDIR) -C -cid -we $< + regmerge $@ /UCR $(subst,.rdb,.urd $@) + +IDL_FILES = \ + types.idl \ + types2_incomp.idl \ + types3_incomp.idl \ + types4_incomp.idl \ + types5_incomp.idl \ + types5.idl \ + types6_incomp.idl + +RDB_FILES = $(foreach,i,$(subst,.idl,.rdb $(IDL_FILES)) $(MISC)$/$(TARGET)$/$i) + +$(SLOFILES): $(RDB_FILES) + +test .PHONY: $(SHL1TARGETN) $(RDB_FILES) + uno -c test.tdmanager.impl -l $(subst,$/,/ $(SHL1TARGETN)) \ + -ro $(subst,$/,/ $(SOLARBINDIR)$/udkapi_doc.rdb) \ + -- $(subst,$/,/ $(SOLARBINDIR)$/types_doc.rdb) \ + $(subst,$/,/ $(RDB_FILES)) diff --git a/stoc/test/tdmanager/readme.txt b/stoc/test/tdmanager/readme.txt new file mode 100644 index 000000000000..f4977204960f --- /dev/null +++ b/stoc/test/tdmanager/readme.txt @@ -0,0 +1,4 @@ +This test uses the delivered typemgr.uno dynamic library, not the local one. +(It might work to fix this, changing the test from a UNO component started from +the uno executable to a stand-alone application that bootstraps UNO in a special +way.) diff --git a/stoc/test/tdmanager/testtdmanager.cxx b/stoc/test/tdmanager/testtdmanager.cxx new file mode 100644 index 000000000000..53b793c8fbe4 --- /dev/null +++ b/stoc/test/tdmanager/testtdmanager.cxx @@ -0,0 +1,374 @@ +/************************************************************************* + * + * 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 "com/sun/star/container/XHierarchicalNameAccess.hpp" +#include "com/sun/star/container/XSet.hpp" +#include "com/sun/star/lang/XMain.hpp" +#include "com/sun/star/lang/XSingleComponentFactory.hpp" +#include "com/sun/star/lang/IllegalArgumentException.hpp" +#include "com/sun/star/reflection/XIndirectTypeDescription.hpp" +#include "com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp" +#include "com/sun/star/reflection/XPublished.hpp" +#include "com/sun/star/reflection/XStructTypeDescription.hpp" +#include "com/sun/star/reflection/XTypeDescription.hpp" +#include "com/sun/star/registry/InvalidRegistryException.hpp" +#include "com/sun/star/registry/XRegistryKey.hpp" +#include "com/sun/star/registry/XSimpleRegistry.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/TypeClass.hpp" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uno/XInterface.hpp" +#include "cppuhelper/factory.hxx" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/weak.hxx" +#include "osl/file.h" +#include "osl/thread.h" +#include "rtl/textenc.h" +#include "rtl/ustring.h" +#include "rtl/ustring.hxx" +#include "sal/types.h" +#include "uno/environment.h" +#include "uno/lbnames.h" + +#include /*MSVC trouble: <cstdlib>*/ <stdlib.h> +#include <iostream> +#include <ostream> + +namespace css = com::sun::star; + +namespace { + +class Service: public cppu::WeakImplHelper1< css::lang::XMain > { +public: + virtual sal_Int32 SAL_CALL + run(css::uno::Sequence< rtl::OUString > const & arguments) + throw (css::uno::RuntimeException); + + static rtl::OUString getImplementationName(); + + static css::uno::Sequence< rtl::OUString > getSupportedServiceNames(); + + static css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance( + css::uno::Reference< css::uno::XComponentContext > const & context) + throw (css::uno::Exception); + +private: + explicit Service( + css::uno::Reference< css::uno::XComponentContext > const & context): + m_context(context) + {} + + css::uno::Reference< css::uno::XComponentContext > m_context; +}; + +} + +namespace { + +std::ostream & operator <<(std::ostream & out, rtl::OUString const & value) { + return out << rtl::OUStringToOString(value, RTL_TEXTENCODING_UTF8).getStr(); +} + +void assertTrue(bool argument) { + if (!argument) { + std::cerr + << "assertTrue(" << argument << ") failed" << std::endl; + /*MSVC trouble: std::*/abort(); + } +} + +void assertFalse(bool argument) { + if (argument) { + std::cerr + << "assertFalse(" << argument << ") failed" << std::endl; + /*MSVC trouble: std::*/abort(); + } +} + +template< typename T > void assertEqual(T const & value, T const & argument) { + if (argument != value) { + std::cerr + << "assertEqual(" << value << ", " << argument << ") failed" + << std::endl; + /*MSVC trouble: std::*/abort(); + } +} + +} + +sal_Int32 Service::run(css::uno::Sequence< rtl::OUString > const & arguments) + throw (css::uno::RuntimeException) +{ + css::uno::Reference< css::lang::XMultiComponentFactory > factory( + m_context->getServiceManager()); + assertTrue(factory.is()); + css::uno::Reference< css::container::XHierarchicalNameAccess > manager( + m_context->getValueByName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "/singletons/" + "com.sun.star.reflection.theTypeDescriptionManager"))), + css::uno::UNO_QUERY_THROW); + + //////////////////////////////////////// + // test: add cmd line rdbs to manager + //////////////////////////////////////// + + OSL_ASSERT( arguments.getLength() > 0 ); + css::uno::Reference<css::container::XSet> xSet( + manager, css::uno::UNO_QUERY_THROW ); + for ( sal_Int32 argPos = 0; argPos < arguments.getLength(); ++argPos ) { + rtl::OUString url; + OSL_VERIFY( osl_File_E_None == osl_getFileURLFromSystemPath( + arguments[argPos].pData, &url.pData ) ); + bool supposedToBeCompatible = ! url.endsWithIgnoreAsciiCaseAsciiL( + RTL_CONSTASCII_STRINGPARAM("_incomp.rdb") ); + + css::uno::Reference<css::registry::XSimpleRegistry> xReg( + m_context->getServiceManager()->createInstanceWithContext( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.SimpleRegistry") ), + m_context ), css::uno::UNO_QUERY_THROW ); + xReg->open( url, true /* read-only */, false /* ! create */ ); + css::uno::Any arg( css::uno::makeAny(xReg) ); + css::uno::Reference<css::container::XHierarchicalNameAccess> xTDprov( + m_context->getServiceManager()-> + createInstanceWithArgumentsAndContext( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.comp.stoc." + "RegistryTypeDescriptionProvider") ), + css::uno::Sequence<css::uno::Any>( &arg, 1 ), m_context ), + css::uno::UNO_QUERY_THROW ); + try { + xSet->insert( css::uno::makeAny(xTDprov) ); + if (! supposedToBeCompatible) + std::cerr << "current rdb file: " << + rtl::OUStringToOString( + url, osl_getThreadTextEncoding()).getStr() << std::endl; + assertTrue(supposedToBeCompatible); + } catch (css::lang::IllegalArgumentException &) { + if (supposedToBeCompatible) + throw; + assertFalse(supposedToBeCompatible); + } + } + + /////// + + css::uno::Reference< css::reflection::XIndirectTypeDescription > sequence( + manager->getByHierarchicalName( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[][]boolean"))), + css::uno::UNO_QUERY_THROW); + assertEqual(css::uno::TypeClass_SEQUENCE, sequence->getTypeClass()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[][]boolean")), + sequence->getName()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[]boolean")), + sequence->getReferencedType()->getName()); + + css::uno::Reference< css::reflection::XStructTypeDescription > structure( + manager->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.tdmanager.Struct<boolean,test.tdmanager.Struct<" + "any,com.sun.star.uno.XInterface>>"))), + css::uno::UNO_QUERY_THROW); + assertEqual(css::uno::TypeClass_STRUCT, structure->getTypeClass()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.tdmanager.Struct<boolean,test.tdmanager.Struct<" + "any,com.sun.star.uno.XInterface>>")), + structure->getName()); + assertEqual< bool >(false, structure->getBaseType().is()); + assertEqual< sal_Int32 >(1, structure->getMemberTypes().getLength()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.tdmanager.Struct<any,com.sun.star.uno.XInterface>")), + structure->getMemberTypes()[0]->getName()); + assertEqual< sal_Int32 >(1, structure->getMemberNames().getLength()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("s")), + structure->getMemberNames()[0]); + assertEqual< sal_Int32 >(0, structure->getTypeParameters().getLength()); + assertEqual< sal_Int32 >(2, structure->getTypeArguments().getLength()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("boolean")), + structure->getTypeArguments()[0]->getName()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "test.tdmanager.Struct<any,com.sun.star.uno.XInterface>")), + structure->getTypeArguments()[1]->getName()); + + css::uno::Reference< css::reflection::XInterfaceMethodTypeDescription > + method( + manager->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.uno.XComponentContext::getValueByName"))), + css::uno::UNO_QUERY_THROW); + assertEqual(css::uno::TypeClass_INTERFACE_METHOD, method->getTypeClass()); + assertEqual( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.uno.XComponentContext::getValueByName")), + method->getName()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("getValueByName")), + method->getMemberName()); + assertEqual< sal_Int32 >(3, method->getPosition()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("any")), + method->getReturnType()->getName()); + assertEqual< bool >(false, method->isOneway()); + assertEqual< sal_Int32 >(1, method->getParameters().getLength()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Name")), + method->getParameters()[0]->getName()); + assertEqual( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("string")), + method->getParameters()[0]->getType()->getName()); + assertEqual< bool >(true, method->getParameters()[0]->isIn()); + assertEqual< bool >(false, method->getParameters()[0]->isOut()); + assertEqual< sal_Int32 >(0, method->getParameters()[0]->getPosition()); + assertEqual< sal_Int32 >(0, method->getExceptions().getLength()); + + assertFalse( + css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + manager->getByHierarchicalName( + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[]boolean"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY).is()); + assertFalse( + css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + manager->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.beans.XIntroTest::ObjectName"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY).is()); + assertFalse( + css::uno::Reference< css::reflection::XPublished >( + css::uno::Reference< css::reflection::XTypeDescription >( + manager->getByHierarchicalName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.beans.XIntroTest::writeln"))), + css::uno::UNO_QUERY_THROW), + css::uno::UNO_QUERY).is()); + //TODO: check that the reflection of a property of an accumulation-based + // service does not support XPublished + + return 0; +} + +rtl::OUString Service::getImplementationName() { + return rtl::OUString::createFromAscii("test.tdmanager.impl"); +} + +css::uno::Sequence< rtl::OUString > Service::getSupportedServiceNames() { + return css::uno::Sequence< rtl::OUString >(); +} + +css::uno::Reference< css::uno::XInterface > Service::createInstance( + css::uno::Reference< css::uno::XComponentContext > const & context) + throw (css::uno::Exception) +{ + return static_cast< cppu::OWeakObject * >(new Service(context)); +} + +extern "C" void SAL_CALL component_getImplementationEnvironment( + char const ** envTypeName, uno_Environment **) +{ + if (envTypeName != 0) { + *envTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; + } +} + +extern "C" void * SAL_CALL component_getFactory(char const * implName, + void * serviceManager, void *) { + void * p = 0; + if (serviceManager != 0) { + css::uno::Reference< css::lang::XSingleComponentFactory > f; + if (Service::getImplementationName().equalsAscii(implName)) { + f = cppu::createSingleComponentFactory( + &Service::createInstance, Service::getImplementationName(), + Service::getSupportedServiceNames()); + } + if (f.is()) { + f->acquire(); + p = f.get(); + } + } + return p; +} + +namespace { + +bool writeInfo(void * registryKey, rtl::OUString const & implementationName, + css::uno::Sequence< rtl::OUString > const & serviceNames) { + rtl::OUString keyName(rtl::OUString::createFromAscii("/")); + keyName += implementationName; + keyName += rtl::OUString::createFromAscii("/UNO/SERVICES"); + css::uno::Reference< css::registry::XRegistryKey > key; + try { + key = static_cast< css::registry::XRegistryKey * >(registryKey)-> + createKey(keyName); + } catch (css::registry::InvalidRegistryException &) {} + if (!key.is()) { + return false; + } + bool success = true; + for (sal_Int32 i = 0; i < serviceNames.getLength(); ++i) { + try { + key->createKey(serviceNames[i]); + } catch (css::registry::InvalidRegistryException &) { + success = false; + break; + } + } + return success; +} + +} + +extern "C" sal_Bool SAL_CALL component_writeInfo(void *, void * registryKey) { + return registryKey + && writeInfo(registryKey, Service::getImplementationName(), + Service::getSupportedServiceNames()); +} diff --git a/stoc/test/tdmanager/types.idl b/stoc/test/tdmanager/types.idl new file mode 100644 index 000000000000..68644509639c --- /dev/null +++ b/stoc/test/tdmanager/types.idl @@ -0,0 +1,45 @@ +/************************************************************************* + * + * 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 <com/sun/star/uno/XInterface.idl> + +module test { module tdmanager { + +struct Struct<T, U> { U s; }; + +published interface XAnother { + void f(); +}; + +service MyService { + [optional] interface XAnother; + [property, optional] boolean b; +}; + +const long CCC = 5; + +}; }; diff --git a/stoc/test/tdmanager/types2_incomp.idl b/stoc/test/tdmanager/types2_incomp.idl new file mode 100644 index 000000000000..8caec558c4bf --- /dev/null +++ b/stoc/test/tdmanager/types2_incomp.idl @@ -0,0 +1,38 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +module com { module sun { module star { module text { + +typedef long XTextField; + +}; }; }; }; + +module test { module tdmanager { + +const long CCC = 6; + +}; }; diff --git a/stoc/test/tdmanager/types3_incomp.idl b/stoc/test/tdmanager/types3_incomp.idl new file mode 100644 index 000000000000..3cb7436f471a --- /dev/null +++ b/stoc/test/tdmanager/types3_incomp.idl @@ -0,0 +1,33 @@ +/************************************************************************* + * + * 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. + * + ************************************************************************/ + +module test { module tdmanager { + +// added member: +struct Struct<T, U> { U s; long n; }; + +}; }; diff --git a/stoc/test/tdmanager/types4_incomp.idl b/stoc/test/tdmanager/types4_incomp.idl new file mode 100644 index 000000000000..127a90647824 --- /dev/null +++ b/stoc/test/tdmanager/types4_incomp.idl @@ -0,0 +1,42 @@ +/************************************************************************* + * + * 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 <com/sun/star/uno/XInterface.idl> + +module test { module tdmanager { + +published interface XAnother { + // wrong name: + void f2(); +}; + +service MyService { + [optional] interface XAnother; + [property, optional] boolean b; +}; + +}; }; diff --git a/stoc/test/tdmanager/types5.idl b/stoc/test/tdmanager/types5.idl new file mode 100644 index 000000000000..9c09f24015de --- /dev/null +++ b/stoc/test/tdmanager/types5.idl @@ -0,0 +1,45 @@ +/************************************************************************* + * + * 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 <com/sun/star/uno/XInterface.idl> + +module test { module tdmanager { + +published interface XAnother { + void f(); +}; + +service MyService { + [optional] interface XAnother; + // correct order: + [property, optional] boolean b; + [property, optional] boolean b2; +}; + +const long CCC = 5; + +}; }; diff --git a/stoc/test/tdmanager/types5_incomp.idl b/stoc/test/tdmanager/types5_incomp.idl new file mode 100644 index 000000000000..86d94f3b86f8 --- /dev/null +++ b/stoc/test/tdmanager/types5_incomp.idl @@ -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. + * + ************************************************************************/ + +#include <com/sun/star/uno/XInterface.idl> + +module test { module tdmanager { + +published interface XAnother { + void f(); +}; + +service MyService { + [optional] interface XAnother; + // wrong order: + [property, optional] boolean b2; + [property, optional] boolean b; +}; + +}; }; diff --git a/stoc/test/tdmanager/types6_incomp.idl b/stoc/test/tdmanager/types6_incomp.idl new file mode 100644 index 000000000000..98ab905e2f76 --- /dev/null +++ b/stoc/test/tdmanager/types6_incomp.idl @@ -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. + * + ************************************************************************/ + +#include <com/sun/star/uno/XInterface.idl> + +module test { module tdmanager { + +published interface XAnother { + void f(); +}; + +service MyService { + // made non-optional: + interface XAnother; + [property, optional] boolean b; + [property, optional] boolean b2; +}; + +}; }; diff --git a/stoc/test/testconv.cxx b/stoc/test/testconv.cxx new file mode 100644 index 000000000000..0687046512af --- /dev/null +++ b/stoc/test/testconv.cxx @@ -0,0 +1,705 @@ +/************************************************************************* + * + * 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/main.h> +#include <osl/diagnose.h> +#include <rtl/ustrbuf.hxx> +#include <cppuhelper/servicefactory.hxx> + +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/script/XTypeConverter.hpp> +#include <com/sun/star/reflection/FieldAccessMode.hpp> +#include <com/sun/star/registry/XImplementationRegistration.hpp> + +#include <float.h> +#include <stdio.h> + + +using namespace rtl; +using namespace cppu; +using namespace osl; +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::registry; + +const double MIN_DOUBLE = -DBL_MAX; +const double MAX_DOUBLE = DBL_MAX; +const double MIN_FLOAT = -FLT_MAX; +const double MAX_FLOAT = FLT_MAX; + +//================================================================================================== +static void printValue( const Any & rVal ) +{ + // print value + OString aStr( OUStringToOString( rVal.getValueType().getTypeName(), RTL_TEXTENCODING_ISO_8859_1 ) ); + printf( "(%s)", aStr.getStr() ); + + switch (rVal.getValueTypeClass()) + { + case TypeClass_VOID: + printf( "void" ); + break; + case TypeClass_ANY: + if (rVal.hasValue()) + printValue( *(Any *)rVal.getValue() ); + break; + case TypeClass_BOOLEAN: + printf( "%s", (*(sal_Bool *)rVal.getValue() ? "true" : "false") ); + break; + case TypeClass_CHAR: + { + char ar[2]; + ar[0] = (char)*(sal_Unicode *)rVal.getValue(); + ar[1] = 0; + printf( ar ); + break; + } + case TypeClass_BYTE: + printf( "%x", (int)*(sal_Int8 *)rVal.getValue() ); + break; + case TypeClass_SHORT: + printf( "%x", *(sal_Int16 *)rVal.getValue() ); + break; + case TypeClass_UNSIGNED_SHORT: + printf( "%x", *(sal_uInt16 *)rVal.getValue() ); + break; + case TypeClass_LONG: + printf( "%lx", static_cast<long>(*(sal_Int32 *)rVal.getValue()) ); + break; + case TypeClass_UNSIGNED_LONG: + printf( "%lx", static_cast<unsigned long>(*(sal_uInt32 *)rVal.getValue()) ); + break; + case TypeClass_HYPER: + printf( "%lx", (long)*(sal_Int64 *)rVal.getValue() ); + break; + case TypeClass_UNSIGNED_HYPER: + printf( "%lx", (unsigned long)*(sal_uInt64 *)rVal.getValue() ); + break; + case TypeClass_FLOAT: + printf( "%f", *(float *)rVal.getValue() ); + break; + case TypeClass_DOUBLE: + printf( "%g", *(double *)rVal.getValue() ); + break; + case TypeClass_STRING: + { + OString aStr2( OUStringToOString( *(OUString *)rVal.getValue(), RTL_TEXTENCODING_ISO_8859_1 ) ); + printf( aStr2.getStr() ); + break; + } + case TypeClass_ENUM: + { + typelib_EnumTypeDescription * pEnumTD = 0; + TYPELIB_DANGER_GET( (typelib_TypeDescription **)&pEnumTD, rVal.getValueTypeRef() ); + + for ( sal_Int32 nPos = pEnumTD->nEnumValues; nPos--; ) + { + if (pEnumTD->pEnumValues[nPos] == *(int *)rVal.getValue()) + { + printf( OUStringToOString(pEnumTD->ppEnumNames[nPos]->buffer, RTL_TEXTENCODING_ASCII_US).getStr() ); + TYPELIB_DANGER_RELEASE( (typelib_TypeDescription *)pEnumTD ); + return; + } + } + TYPELIB_DANGER_RELEASE( (typelib_TypeDescription *)pEnumTD ); + printf( ">ENUM not found!<" ); + break; + } + case TypeClass_SEQUENCE: + { + uno_Sequence * pSeq = *(uno_Sequence **)rVal.getValue(); + typelib_TypeDescription * pSeqTD = 0; + TYPELIB_DANGER_GET( &pSeqTD, rVal.getValueTypeRef() ); + typelib_TypeDescription * pElemTD = 0; + TYPELIB_DANGER_GET( &pElemTD, ((typelib_IndirectTypeDescription *)pSeqTD)->pType ); + + sal_Int32 nLen = pSeq->nElements; + if (nLen) + { + printf( "{ " ); + for ( sal_Int32 nPos = 0; nPos < nLen; ++nPos ) + { + printValue( Any( ((char *)pSeq->elements) + (nPos * pElemTD->nSize), pElemTD ) ); + if (nPos < (nLen-1)) + printf( ", " ); + } + printf( " }" ); + } + + TYPELIB_DANGER_RELEASE( pElemTD ); + TYPELIB_DANGER_RELEASE( pSeqTD ); + break; + } + + default: + printf( ">not printable<" ); + break; + } +} + +static Reference< XTypeConverter > s_xConverter; + +//================================================================================================== +static sal_Bool convertTo( const Type & rDestType, const Any & rVal, sal_Bool bExpectSuccess ) +{ + sal_Bool bCanConvert = sal_False; + Any aRet; + + OString aExcMsg; + + try + { + aRet = s_xConverter->convertTo( rVal, rDestType ); + bCanConvert = sal_True; + } + catch (Exception & rExc) + { + aExcMsg = OUStringToOString( rExc.Message, RTL_TEXTENCODING_ASCII_US ); + } + + if (bExpectSuccess && !bCanConvert) + { + printf( "# conversion of " ); + printValue( rVal ); + printf( " to " ); + printf( OUStringToOString(rDestType.getTypeName(), RTL_TEXTENCODING_ASCII_US).getStr() ); + printf( " failed, but success was expected! [" ); + printf( aExcMsg.getStr() ); + printf( "]\n" ); + aRet = s_xConverter->convertTo( rVal, rDestType ); +#if OSL_DEBUG_LEVEL > 1 + // for debugging, to trace again + try + { + aRet = s_xConverter->convertTo( rVal, rDestType ); + } + catch (Exception &) + { + } +#endif + return sal_False; + } + if (!bExpectSuccess && bCanConvert) + { + printf( "# conversion of " ); + printValue( rVal ); + printf( " to " ); + printValue( aRet ); + printf( " was successful, but was not expected to be!\n" ); +#if OSL_DEBUG_LEVEL > 1 + // for debugging, to trace again + aRet = s_xConverter->convertTo( rVal, rDestType ); +#endif + return sal_False; + } + +#ifdef __RECONVERSION_OUTPUT__ +//= re-conversion output = + if (bCanConvert) + { + // re convert to original type + sal_Bool bReConvert = sal_False; + Any aRet2; + + try + { + aRet2 = s_xConverter->convertTo( aRet, rVal.getValueType() ); + bReConvert = sal_True; + } + catch (Exception & rExc) + { + aExcMsg = OUStringToOString( rExc.Message, RTL_TEXTENCODING_ISO_8859_1 ); + } + + if (bReConvert) + { + if (rVal != aRet2) + { + printf( "# re-conversion of " ); + printValue( rVal ); + printf( " to " ); + printValue( aRet ); + printf( " to " ); + printValue( aRet2 ); + printf( ": first and last do not match!\n" ); + } + } + else + { + printf( "# re-conversion of " ); + printValue( aRet ); + printf( " to " ); + printf( rVal.getValueType().getTypeName().getStr() ); + printf( " failed! [" ); + printf( aExcMsg.getStr() ); + printf( "]\n" ); + } + } +#endif + + return sal_True; +} + + +//================================================================================================== +typedef struct _ConvBlock +{ + Any _value; + sal_Bool _toString, _toDouble, _toFloat; + sal_Bool _toUINT32, _toINT32, _toUINT16, _toINT16, _toBYTE, _toBOOL, _toChar; + sal_Bool _toTypeClass, _toSeqINT16, _toSeqAny; + + _ConvBlock() + { + } + _ConvBlock( const Any & rValue_, + sal_Bool toString_, sal_Bool toDouble_, sal_Bool toFloat_, + sal_Bool toUINT32_, sal_Bool toINT32_, sal_Bool toUINT16_, sal_Bool toINT16_, + sal_Bool toBYTE_, sal_Bool toBOOL_, sal_Bool toChar_, + sal_Bool toTypeClass_, sal_Bool toSeqINT16_, sal_Bool toSeqAny_ ) + : _value( rValue_ ) + , _toString( toString_ ), _toDouble( toDouble_ ), _toFloat( toFloat_ ) + , _toUINT32( toUINT32_ ), _toINT32( toINT32_ ), _toUINT16( toUINT16_ ), _toINT16( toINT16_ ) + , _toBYTE( toBYTE_ ), _toBOOL( toBOOL_ ), _toChar( toChar_ ) + , _toTypeClass( toTypeClass_ ), _toSeqINT16( toSeqINT16_ ), _toSeqAny( toSeqAny_ ) + { + } +} ConvBlock; + + +//================================================================================================== +static sal_Int32 initBlocks( ConvBlock * pTestBlocks ) +{ + Any aVal; + + sal_uInt32 nElems = 0; + + // ==BYTE== + aVal <<= OUString::createFromAscii( "0xff" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 ); + aVal <<= OUString::createFromAscii( "255" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 ); + aVal <<= (sal_Int8)0xffu; + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "0x80" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 ); + aVal <<= OUString::createFromAscii( "128" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 ); + aVal <<= (sal_Int8)( 0x80u ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "0x7f" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 ); + aVal <<= OUString::createFromAscii( "127" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 ); + aVal <<= (sal_Int8)( 0x7f ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "5" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0 ); + aVal <<= OUString::createFromAscii( "+5" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 ); + aVal <<= (sal_Int8)( 5 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "-5" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (sal_Int8)( -5 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "256" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + // ==UINT16== + aVal <<= OUString::createFromAscii( "65535" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 ); + aVal <<= OUString::createFromAscii( "0xffff" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 ); + aVal <<= (sal_uInt16)( 0xffff ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "32768" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 ); + aVal <<= (sal_uInt16)( 0x8000 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "32767" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 ); + aVal <<= OUString::createFromAscii( "0x7fff" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 ); + aVal <<= (sal_uInt16)( 0x7fff ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "256" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 ); + aVal <<= OUString::createFromAscii( "0x100" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 ); + aVal <<= (sal_uInt16)( 0x100 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (sal_uInt16)( 5 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (sal_uInt16)( -5 ); // is 0xfffb + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + // ==INT16== + aVal <<= (sal_Int16)( -1 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (sal_Int16)( -0x8000 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (sal_Int16)( 0x7fff ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (sal_Int16)( 0x100 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (sal_Int16)( 5 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (sal_Int16)( -5 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + // ==UINT32== + aVal <<= OUString::createFromAscii( "+4294967295" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + aVal <<= OUString::createFromAscii( "4294967295" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + aVal <<= OUString::createFromAscii( "0xffffffff" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + aVal <<= (sal_uInt32)( 0xffffffff ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "-2147483648" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 ); + aVal <<= OUString::createFromAscii( "-0x80000000" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (sal_uInt32)( 0x80000000 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "2147483647" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 ); + aVal <<= OUString::createFromAscii( "0x7fffffff" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 ); + aVal <<= (sal_uInt32)( 0x7fffffff ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "65536" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 ); + aVal <<= OUString::createFromAscii( "0x10000" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 ); + aVal <<= (sal_uInt32)( 0x10000 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (sal_uInt32)( 0x8000 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (sal_uInt32)( 5 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "0xfffffffb" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + aVal <<= (sal_uInt32)( -5 ); // is 0xfffffffb + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + // ==INT32== + aVal <<= (sal_Int32)( 0xffffffff ); // is -1 + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (sal_Int32)( 0x80000000 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (sal_Int32)( 0x7fffffff ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (sal_Int32)( 0x10000 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (sal_Int32)( -0x8001 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (sal_Int32)( 5 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (sal_Int32)( -5 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + // ==FLOAT== + aVal <<= OUString::createFromAscii( "-3.4e+38" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + aVal <<= (float)( MIN_FLOAT ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "+3.4e+38" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + aVal <<= (float)( MAX_FLOAT ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "9e-20" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 ); + aVal <<= (float)( 9e-20 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "+.7071067811865" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 ); + aVal <<= (float)( .7071067811865 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "3.14159265359" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 ); + aVal <<= (float)( 3.14159265359 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (float)( 5 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + // ==DOUBLE== + aVal <<= OUString::createFromAscii( "-1.7976931348623155e+308" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + aVal <<= (double)( MIN_DOUBLE ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "1.7976931348623155e+308" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + aVal <<= (double)( MAX_DOUBLE ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (double)( MIN_FLOAT ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (double)( MAX_FLOAT ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (double)( -((double)0x80000000) ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (double)( -((double)0x80000001) ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (double)( 0x7fffffff ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (double)( 0x80000000 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (double)( 0xffffffff ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "0x100000000" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); +#ifndef OS2 + aVal <<= (double)( SAL_CONST_INT64(0x100000000) ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ); +#endif + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= (double)( 5 ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + // ==CHAR== + sal_Unicode c = 'A'; + aVal.setValue( &c, ::getCharCppuType() ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "A" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + // ==BOOL== + aVal <<= OUString::createFromAscii( "0" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "1" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "False" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "true" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + + sal_Bool bTmp = sal_True; + aVal.setValue( &bTmp, getBooleanCppuType() ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + // ==ZERO STRINGS== + aVal <<= OUString(); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "-" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "-0" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + // ==TYPECLASS ENUM== + aVal <<= OUString::createFromAscii( "eNuM" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal <<= OUString::createFromAscii( "DOUBLE" ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + int e = 1; + aVal.setValue( &e, ::getCppuType( (const TypeClass *)0 ) ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + aVal.setValue( &e, ::getCppuType( (const FieldAccessMode *)0 ) ); + pTestBlocks[nElems++] = ConvBlock( aVal, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + // ==SEQ of INT== + Sequence< sal_Int32 > aINT32Seq( 3 ), aINT32Seq2( 3 ); + sal_Int32 * pINT32Seq = aINT32Seq.getArray(); + pINT32Seq[0] = -32768; + pINT32Seq[1] = 0; + pINT32Seq[2] = 32767; + aVal <<= aINT32Seq; + pTestBlocks[nElems++] = ConvBlock( aVal, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + pINT32Seq = aINT32Seq2.getArray(); + pINT32Seq[0] = -32768; + pINT32Seq[1] = -32769; + pINT32Seq[2] = 32767; + aVal <<= aINT32Seq2; + pTestBlocks[nElems++] = ConvBlock( aVal, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + // ==SEQ of ANY== + Sequence< Any > aAnySeq( 2 ), aAnySeq2( 2 ), aAnySeq3( 2 ); + Any * pAnySeq = aAnySeq.getArray(); + pAnySeq[0] = makeAny( aINT32Seq ); + pAnySeq[1] = makeAny( OUString::createFromAscii("lala") ); + aVal <<= aAnySeq; + pTestBlocks[nElems++] = ConvBlock( aVal, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + pAnySeq = aAnySeq2.getArray(); + pAnySeq[0] <<= (sal_Int32)4711; + pAnySeq[1] <<= OUString::createFromAscii("0815"); + aVal <<= aAnySeq2; + pTestBlocks[nElems++] = ConvBlock( aVal, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + pAnySeq = aAnySeq3.getArray(); + pAnySeq[0] <<= OUString::createFromAscii("TypeClass_UNION"); + pAnySeq[1] <<= OUString::createFromAscii("TypeClass_ENUM"); + aVal <<= aAnySeq3; + pTestBlocks[nElems++] = ConvBlock( aVal, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ); + // st,do,fl,u3,i3,u1,i1,by,bo,ch,tc,si,sa + return nElems; +} + +//================================================================================================== +static void test_Conversion( const Reference< XMultiServiceFactory > & xMgr ) +{ + printf( "test_Conversion(): start...\n" ); + + Reference< XTypeConverter > xConverter( xMgr->createInstance( + OUString::createFromAscii( "com.sun.star.script.Converter" ) ), UNO_QUERY ); + + ConvBlock * pTestBlocks = new ConvBlock[256]; + sal_Int32 nPos = initBlocks( pTestBlocks ); + + s_xConverter = xConverter; + while (nPos--) + { + const ConvBlock& rBlock = pTestBlocks[nPos]; + const Any & rVal = rBlock._value; + + convertTo( ::getCppuType( (const OUString *)0 ), rVal, rBlock._toString ); + convertTo( ::getCppuType( (const float *)0 ), rVal, rBlock._toFloat ); + convertTo( ::getCppuType( (const double *)0 ), rVal, rBlock._toDouble ); + convertTo( ::getCppuType( (const sal_uInt32 *)0 ), rVal, rBlock._toUINT32 ); + convertTo( ::getCppuType( (const sal_Int32 *)0 ), rVal, rBlock._toINT32 ); + convertTo( ::getCppuType( (const sal_uInt16 *)0 ), rVal, rBlock._toUINT16 ); + convertTo( ::getCppuType( (const sal_Int16 *)0 ), rVal, rBlock._toINT16 ); + convertTo( ::getCppuType( (const sal_Int8 *)0 ), rVal, rBlock._toBYTE ); + convertTo( ::getBooleanCppuType(), rVal, rBlock._toBOOL ); + convertTo( ::getCharCppuType(), rVal, rBlock._toChar ); + convertTo( ::getCppuType( (const TypeClass *)0 ), rVal, rBlock._toTypeClass ); + convertTo( ::getCppuType( (const Sequence< sal_Int16 > *)0 ), rVal, rBlock._toSeqINT16 ); + convertTo( ::getCppuType( (const Sequence< Any > *)0 ), rVal, rBlock._toSeqAny ); + + convertTo( ::getVoidCppuType(), rVal, sal_True ); // anything converts to void + } + s_xConverter.clear(); + + delete [] pTestBlocks; + + Any aRet; + aRet = xConverter->convertTo( Any( &xMgr, ::getCppuType( (const Reference< XMultiServiceFactory > *)0 ) ), + ::getCppuType( (const Reference< XServiceInfo > *)0 ) ); + aRet = xConverter->convertTo( aRet, ::getCppuType( (const Reference< XMultiServiceFactory > *)0 ) ); + aRet = xConverter->convertTo( aRet, ::getCppuType( (const Reference< XServiceInfo > *)0 ) ); + aRet <<= SAL_CONST_INT64(0x7fffffffffffffff); + aRet = xConverter->convertTo( aRet, ::getCppuType( (const sal_uInt64 *)0 ) ); + OSL_ASSERT( *(const sal_uInt64 *)aRet.getValue() == SAL_CONST_UINT64(0x7fffffffffffffff) ); + aRet <<= SAL_CONST_UINT64(0xffffffffffffffff); + aRet = xConverter->convertTo( aRet, ::getCppuType( (const sal_uInt64 *)0 ) ); + OSL_ASSERT( *(const sal_uInt64 *)aRet.getValue() == SAL_CONST_UINT64(0xffffffffffffffff) ); + aRet <<= SAL_CONST_INT64(-1); + aRet = xConverter->convertTo( aRet, ::getCppuType( (const sal_Int8 *)0 ) ); + OSL_ASSERT( *(const sal_Int8 *)aRet.getValue() == (-1) ); + printf( "test_Conversion(): end.\n" ); +} + +SAL_IMPLEMENT_MAIN() +{ + Reference< XMultiServiceFactory > xMgr( createRegistryServiceFactory( OUString::createFromAscii("stoctest.rdb") ) ); + + try + { + Reference< XImplementationRegistration > xImplReg( + xMgr->createInstance( OUString::createFromAscii("com.sun.star.registry.ImplementationRegistration") ), UNO_QUERY ); + OSL_ENSURE( xImplReg.is(), "### no impl reg!" ); + + OUString aLibName( + RTL_CONSTASCII_USTRINGPARAM("stocservices.uno" SAL_DLLEXTENSION) ); + xImplReg->registerImplementation( + OUString::createFromAscii("com.sun.star.loader.SharedLibrary"), + aLibName, Reference< XSimpleRegistry >() ); + + test_Conversion( xMgr ); + } + catch (Exception & rExc) + { + OSL_ENSURE( sal_False, "### exception occured!" ); + OString aMsg( OUStringToOString( rExc.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( "### exception occured: " ); + OSL_TRACE( aMsg.getStr() ); + OSL_TRACE( "\n" ); + } + + Reference< XComponent >( xMgr, UNO_QUERY )->dispose(); + return 0; +} diff --git a/stoc/test/testcorefl.cxx b/stoc/test/testcorefl.cxx new file mode 100644 index 000000000000..31cc9fc18b8a --- /dev/null +++ b/stoc/test/testcorefl.cxx @@ -0,0 +1,412 @@ +/************************************************************************* + * + * 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/main.h> +#include <osl/diagnose.h> + +#if OSL_DEBUG_LEVEL > 0 +#define TEST_ENSHURE(c, m) OSL_ENSURE(c, m) +#else +#define TEST_ENSHURE(c, m) OSL_VERIFY(c) +#endif + +#include <cppuhelper/servicefactory.hxx> +#include <cppuhelper/weak.hxx> +#include <cppuhelper/implbase1.hxx> + +#include <ModuleA/XInterface1.hpp> +#include <ModuleC/XInterfaceA.hpp> +#include <ModuleC/XInterfaceB.hpp> +#include <ModuleC/ModuleC.hpp> + +#include <com/sun/star/container/XHierarchicalNameAccess.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/reflection/XIdlReflection.hpp> +#include <com/sun/star/reflection/XIdlField2.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/registry/XSimpleRegistry.hpp> +#include <com/sun/star/registry/XImplementationRegistration.hpp> + +#include <rtl/ustrbuf.hxx> + +#include <stdio.h> + + +using namespace rtl; +using namespace cppu; +using namespace osl; +using namespace ModuleA; +using namespace ModuleB; +using namespace ModuleC; +using namespace ModuleA::ModuleB; +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::registry; +using namespace com::sun::star::reflection; +using namespace com::sun::star::container; + + +//================================================================================================== +class OInterfaceA : public WeakImplHelper1< XInterfaceA > +{ +public: + + virtual void SAL_CALL methodA(void) throw (RuntimeException) + {} + + virtual void SAL_CALL methodB(sal_Int16 /*aShort*/) throw (RuntimeException) + {} + virtual Sequence< StructB > SAL_CALL methodC(const StructC& /*aStructC*/, StructA& /*aStructA*/) throw (RuntimeException) + { return Sequence< StructB >(); } +}; + +//================================================================================================== +static inline bool uik_equals( const Uik & rUik1, const Uik & rUik2 ) +{ + return (rUik1.m_Data1 == rUik2.m_Data1 && + rUik1.m_Data2 == rUik2.m_Data2 && + rUik1.m_Data3 == rUik2.m_Data3 && + rUik1.m_Data4 == rUik2.m_Data4 && + rUik1.m_Data5 == rUik2.m_Data5); +} +//================================================================================================== +static sal_Bool test_corefl( const Reference< XIdlReflection > & xRefl ) +{ + Reference< XIdlClass > xClass; + Reference< XHierarchicalNameAccess > xHNameAccess( xRefl, UNO_QUERY ); + TEST_ENSHURE(xHNameAccess.is(), "### cannot get XHierarchicalNameAccess!" ); + + TEST_ENSHURE(xRefl->forName(OUString::createFromAscii("ModuleA.StructA"))->getName() == OUString::createFromAscii("ModuleA.StructA"), "test_RegCoreReflection(): error 2b"); + TEST_ENSHURE(xRefl->forName(OUString::createFromAscii("ModuleA.ExceptionB"))->getTypeClass() == TypeClass_EXCEPTION, "test_RegCoreReflection(): error 2c"); + TEST_ENSHURE(xRefl->forName(OUString::createFromAscii("ModuleA.ModuleB.EnumA")).is(), "test_RegCoreReflection(): error 2e"); + // const + + TEST_ENSHURE(*(const sal_Bool *)xHNameAccess->getByHierarchicalName(OUString::createFromAscii("ModuleC.aConstBoolean")).getValue() == aConstBoolean, "test_RegCoreReflection(): error 4c"); + TEST_ENSHURE(*(const sal_Int8 *)xHNameAccess->getByHierarchicalName(OUString::createFromAscii("ModuleC.aConstByte")).getValue() == aConstByte, "test_RegCoreReflection(): error 4e"); + TEST_ENSHURE(xHNameAccess->getByHierarchicalName(OUString::createFromAscii("ModuleC.aConstShort")) == aConstShort, "test_RegCoreReflection(): error 4g"); + TEST_ENSHURE(xHNameAccess->getByHierarchicalName(OUString::createFromAscii("ModuleC.aConstUShort")) == aConstUShort, "test_RegCoreReflection(): error 4i"); + TEST_ENSHURE(xHNameAccess->getByHierarchicalName(OUString::createFromAscii("ModuleC.aConstLong")) == aConstLong, "test_RegCoreReflection(): error 4k"); + TEST_ENSHURE(xHNameAccess->getByHierarchicalName(OUString::createFromAscii("ModuleC.aConstULong")) == aConstULong, "test_RegCoreReflection(): error 4m"); +// TEST_ENSHURE(xHNameAccess->getByHierarchicalName(OUString::createFromAscii("ModuleC.aConstFloat")) == aConstFloat, "test_RegCoreReflection(): error 4o"); +// TEST_ENSHURE(xHNameAccess->getByHierarchicalName(OUString::createFromAscii("ModuleC.aConstDouble")) == aConstDouble, "test_RegCoreReflection(): error 4q"); + + // Enums + + xClass = xRefl->forName(OUString::createFromAscii("ModuleA.ModuleB.EnumA")); + + TEST_ENSHURE(xClass.is(), "test_RegCoreReflection(): error 5"); + + Sequence<Reference< XIdlField > > fields = xClass->getFields(); + + TEST_ENSHURE( + (fields.getLength() == 3) && + (fields.getArray()[0]->getName() == OUString( RTL_CONSTASCII_USTRINGPARAM("VAL_1") )) && + (*(EnumA*)fields.getArray()[0]->get(Any()).getValue() == EnumA_VAL_1) && + (fields.getArray()[1]->getName() == OUString( RTL_CONSTASCII_USTRINGPARAM("VAL_2") )) && + (*(EnumA*)fields.getArray()[1]->get(Any()).getValue() == EnumA_VAL_2) && + (fields.getArray()[2]->getName() == OUString( RTL_CONSTASCII_USTRINGPARAM("VAL_3") )) && + (*(EnumA*)fields.getArray()[2]->get(Any()).getValue() == EnumA_VAL_3), + "test_RegCoreReflection(): error 6"); + + + // Interface + + Reference< XIdlClass > xA = xRefl->forName( OUString::createFromAscii("ModuleC.XInterfaceB") ); + + xClass = xRefl->forName(OUString::createFromAscii("ModuleC.XInterfaceB")); + + TEST_ENSHURE(xClass == xA, "test_RegCoreReflection(): error 7"); + TEST_ENSHURE(xClass.is(), "test_RegCoreReflection(): error 7a"); + + typelib_TypeDescription * pTD = 0; + OUString aModuleName( RTL_CONSTASCII_USTRINGPARAM("ModuleC.XInterfaceB") ); + typelib_typedescription_getByName( &pTD, aModuleName.pData ); + TEST_ENSHURE( pTD, "### cannot get typedescription for ModuleC.XInterfaceB!" ); + + TEST_ENSHURE( uik_equals( *(Uik *)&((typelib_InterfaceTypeDescription *)pTD)->aUik, + xClass->getUik() ), + "test_RegCoreReflection(): error 8" ); + typelib_typedescription_release( pTD ); + + TEST_ENSHURE(xClass->getSuperclasses().getLength() == 1, "test_RegCoreReflection(): error 9"); + TEST_ENSHURE(xClass->getSuperclasses().getArray()[0]->getName() == OUString::createFromAscii("ModuleC.XInterfaceA"), "test_RegCoreReflection(): error 10"); + TEST_ENSHURE(xClass->getMethods().getLength() == 7, "test_RegCoreReflection(): error 11"); + TEST_ENSHURE(xA->getMethods().getLength() == 7, "test_RegCoreReflection(): error 11a"); + TEST_ENSHURE(xClass->getMethods().getArray()[3]->getName() == OUString::createFromAscii("methodA"), "test_RegCoreReflection(): 12"); + TEST_ENSHURE(xClass->getMethods().getArray()[3]->getReturnType()->getTypeClass() == TypeClass_VOID, "test_RegCoreReflection(): error 13"); + TEST_ENSHURE(xClass->getMethods().getArray()[3]->getParameterTypes().getLength() == 0, "test_RegCoreReflection(): error 14"); + TEST_ENSHURE(xClass->getMethods().getArray()[3]->getExceptionTypes().getLength() == 0, "test_RegCoreReflection(): error 15"); + TEST_ENSHURE(xClass->getMethods().getArray()[4]->getName() == OUString( RTL_CONSTASCII_USTRINGPARAM("methodB") ), "test_RegCoreReflection(): error 16"); + TEST_ENSHURE(xClass->getMethods().getArray()[4]->getMode() == MethodMode_ONEWAY, "test_RegCoreReflection(): error 16a"); + TEST_ENSHURE(xClass->getMethods().getArray()[4]->getReturnType()->getTypeClass() == TypeClass_VOID, "test_RegCoreReflection(): error 16"); + TEST_ENSHURE(xClass->getMethods().getArray()[4]->getParameterTypes().getLength() == 1, "test_RegCoreReflection(): error 17"); + TEST_ENSHURE(xClass->getMethods().getArray()[4]->getParameterTypes().getArray()[0]->getTypeClass() == TypeClass_SHORT, "test_RegCoreReflection(): error 18"); + TEST_ENSHURE(xClass->getMethods().getArray()[4]->getParameterInfos().getArray()[0].aName == OUString( RTL_CONSTASCII_USTRINGPARAM("aShort") ), "test_RegCoreReflection(): error 18a"); + TEST_ENSHURE(xClass->getMethods().getArray()[4]->getParameterInfos().getArray()[0].aType == xRefl->forName( OUString( RTL_CONSTASCII_USTRINGPARAM("short") ) ), "test_RegCoreReflection(): error 18b"); + TEST_ENSHURE(xClass->getMethods().getArray()[4]->getParameterInfos().getArray()[0].aMode == ParamMode_IN, "test_RegCoreReflection(): error 18c"); + TEST_ENSHURE(xClass->getMethods().getArray()[4]->getExceptionTypes().getLength() == 0, "test_RegCoreReflection(): error 19"); + TEST_ENSHURE(xClass->getMethods().getArray()[5]->getName() == OUString::createFromAscii("methodC"), "test_RegCoreReflection(): error 20"); + TEST_ENSHURE(xClass->getMethods().getArray()[5]->getMode() == MethodMode_TWOWAY, "test_RegCoreReflection(): error 20a"); + TEST_ENSHURE(xClass->getMethods().getArray()[5]->getReturnType()->getTypeClass() == TypeClass_SEQUENCE, "test_RegCoreReflection(): error 21"); + TEST_ENSHURE(xClass->getMethods().getArray()[5]->getReturnType()->getComponentType()->getTypeClass() == TypeClass_STRUCT, "test_RegCoreReflection(): error 22"); + TEST_ENSHURE(xClass->getMethods().getArray()[5]->getReturnType()->getComponentType()->getName() == OUString::createFromAscii("ModuleA.StructB"), "test_RegCoreReflection(): error 23"); + TEST_ENSHURE(xClass->getMethods().getArray()[5]->getParameterTypes().getLength() == 2, "test_RegCoreReflection(): error 24"); + TEST_ENSHURE(xClass->getMethods().getArray()[5]->getParameterTypes().getArray()[0]->getTypeClass() == TypeClass_STRUCT, "test_RegCoreReflection(): error 25"); + TEST_ENSHURE(xClass->getMethods().getArray()[5]->getParameterTypes().getArray()[0]->getName() == OUString::createFromAscii("ModuleA.StructC"), "test_RegCoreReflection(): error 26"); + TEST_ENSHURE(xClass->getMethods().getArray()[5]->getParameterTypes().getArray()[1]->getTypeClass() == TypeClass_STRUCT, "test_RegCoreReflection(): error 27"); + TEST_ENSHURE(xClass->getMethods().getArray()[5]->getParameterTypes().getArray()[1]->getName() == OUString::createFromAscii("ModuleA.StructA"), "test_RegCoreReflection(): error 28"); + TEST_ENSHURE(xClass->getMethods().getArray()[5]->getExceptionTypes().getLength() == 0, "test_RegCoreReflection(): error 29"); + TEST_ENSHURE(xClass->getMethods().getArray()[6]->getName() == OUString::createFromAscii("methodD"), "test_RegCoreReflection(): error 30"); + TEST_ENSHURE(xClass->getMethods().getArray()[6]->getReturnType()->getTypeClass() == TypeClass_INTERFACE, "test_RegCoreReflection(): error 31"); + TEST_ENSHURE(xClass->getMethods().getArray()[6]->getReturnType()->getName() == OUString::createFromAscii("ModuleC.XInterfaceA"), "test_RegCoreReflection(): error 32"); + TEST_ENSHURE(xClass->getMethods().getArray()[6]->getParameterTypes().getLength() == 1, "test_RegCoreReflection(): error 33"); + TEST_ENSHURE(xClass->getMethods().getArray()[6]->getParameterTypes().getArray()[0]->getTypeClass() == TypeClass_ENUM, "test_RegCoreReflection(): error 34"); + TEST_ENSHURE(xClass->getMethods().getArray()[6]->getParameterTypes().getArray()[0]->getName() == OUString::createFromAscii("ModuleA.ModuleB.EnumA"), "test_RegCoreReflection(): error 35"); + TEST_ENSHURE(xClass->getMethods().getArray()[6]->getExceptionTypes().getLength() == 3, "test_RegCoreReflection(): error 36"); + TEST_ENSHURE(xClass->getMethods().getArray()[6]->getExceptionTypes().getArray()[0]->getTypeClass() == TypeClass_EXCEPTION, "test_RegCoreReflection(): error 37"); + TEST_ENSHURE(xClass->getMethods().getArray()[6]->getExceptionTypes().getArray()[0]->getName() == OUString::createFromAscii("ModuleA.ExceptionA"), "test_RegCoreReflection(): error 38"); + TEST_ENSHURE(xClass->getMethods().getArray()[6]->getExceptionTypes().getArray()[1]->getTypeClass() == TypeClass_EXCEPTION, "test_RegCoreReflection(): error 38"); + TEST_ENSHURE(xClass->getMethods().getArray()[6]->getExceptionTypes().getArray()[1]->getName() == OUString::createFromAscii("ModuleA.ExceptionB"), "test_RegCoreReflection(): error 39"); + TEST_ENSHURE(xClass->getMethods().getArray()[6]->getExceptionTypes().getArray()[2]->getTypeClass() == TypeClass_EXCEPTION, "test_RegCoreReflection(): error 40"); + TEST_ENSHURE(xClass->getMethods().getArray()[6]->getExceptionTypes().getArray()[2]->getName() == OUString::createFromAscii("ModuleA.ExceptionC"), "test_RegCoreReflection(): error 41"); + TEST_ENSHURE(xClass->getMethods().getArray()[6]->getExceptionTypes().getArray()[2]->getFields().getLength() == 3, "test_RegCoreReflection(): error 42"); + TEST_ENSHURE(xClass->getMethods().getArray()[6]->getExceptionTypes().getArray()[2]->getFields().getArray()[0]->getType()->getTypeClass() == TypeClass_BOOLEAN, "test_RegCoreReflection(): error 43"); + TEST_ENSHURE(xClass->getMethods().getArray()[6]->getExceptionTypes().getArray()[2]->getFields().getArray()[0]->getType()->getName() == OUString::createFromAscii("boolean"), "test_RegCoreReflection(): error 43a"); + TEST_ENSHURE(xClass->getMethods().getArray()[6]->getExceptionTypes().getArray()[2]->getFields().getArray()[1]->getType()->getTypeClass() == TypeClass_STRUCT, "test_RegCoreReflection(): error 44"); + TEST_ENSHURE(xClass->getMethods().getArray()[6]->getExceptionTypes().getArray()[2]->getFields().getArray()[1]->getType()->getName() == OUString::createFromAscii("ModuleA.StructC"), "test_RegCoreReflection(): error 45"); + TEST_ENSHURE(xClass->getMethods().getArray()[6]->getExceptionTypes().getArray()[2]->getFields().getArray()[2]->getType()->getTypeClass() == TypeClass_INTERFACE, "test_RegCoreReflection(): error 46"); + TEST_ENSHURE(xClass->getMethods().getArray()[6]->getExceptionTypes().getArray()[2]->getFields().getArray()[2]->getType()->getName() == OUString::createFromAscii("ModuleA.XInterface1"), "test_RegCoreReflection(): error 47"); + + // SequenceReflections + + TEST_ENSHURE(xRefl->forName( OUString::createFromAscii("[]ModuleA.StructA") )->getTypeClass() == TypeClass_SEQUENCE, "test_RegCoreReflection(): error 48"); + TEST_ENSHURE(xRefl->forName( OUString::createFromAscii("[]ModuleA.StructA") )->getComponentType().is(), "test_RegCoreReflection(): error 49"); + TEST_ENSHURE(xRefl->forName( OUString::createFromAscii("[][]ModuleA.StructA") )->getComponentType()->getComponentType()->getName() == OUString::createFromAscii("ModuleA.StructA"), "test_RegCoreReflection(): error 50"); + TEST_ENSHURE(xRefl->forName( OUString::createFromAscii("[]com.sun.star.uno.XInterface") ) == xRefl->forName(OUString( RTL_CONSTASCII_USTRINGPARAM("ModuleA.StructC") ))->getField(OUString::createFromAscii("aInterfaceSeq"))->getType(), "test_RegCoreReflection(): error 51"); + + StructC aStructC; + aStructC.aLong = aConstLong; + aStructC.aShort = aConstShort; + aStructC.aFloat = aConstFloat; + aStructC.aDouble = aConstDouble; + aStructC.aInterfaceSeq = Sequence<Reference<XInterface > >(); + + Any aAny; + + xRefl->forName(OUString::createFromAscii("ModuleA.StructC"))->getField(OUString::createFromAscii("aInterfaceSeq"))->getType()->createObject(aAny); + + TEST_ENSHURE(aAny.getValueType() == ::getCppuType( (const Sequence<Reference< XInterface > > *)0 ), "test_RegCoreReflection(): error 51a"); + + Any aStructAny(&aStructC, ::getCppuType( (const StructC *) 0 )); + + sal_Int32 nLong = aConstLong * 2; + aAny.setValue( &nLong, ::getCppuType( (const sal_Int32 *)0 ) ); + + TEST_ENSHURE(*(sal_Int32*)xRefl->forName(OUString( RTL_CONSTASCII_USTRINGPARAM("ModuleA.StructA") ))->getField(OUString( RTL_CONSTASCII_USTRINGPARAM("aLong") ))->get( + Any(&aStructC, ::getCppuType( (const StructC *)0 ))).getValue() == aConstLong, "test_RegCoreReflection(): error 52"); + TEST_ENSHURE(xRefl->forName(OUString::createFromAscii("ModuleA.StructA"))->getField(OUString( RTL_CONSTASCII_USTRINGPARAM("aLong") ))->getAccessMode() == FieldAccessMode_READWRITE, "test_RegCoreReflection(): error 52a"); + Reference< XIdlField2 > rField ( xRefl->forName(OUString( RTL_CONSTASCII_USTRINGPARAM("ModuleA.StructC") ))->getField(OUString( RTL_CONSTASCII_USTRINGPARAM("aLong") )) , UNO_QUERY ); + rField->set(aStructAny, aAny); + TEST_ENSHURE(*(sal_Int32*)xRefl->forName(OUString::createFromAscii("ModuleA.StructB"))->getField(OUString( RTL_CONSTASCII_USTRINGPARAM("aLong") ))->get(aStructAny).getValue() == *(sal_Int32*)aAny.getValue(), "test_RegCoreReflection(): error 53"); + + xRefl->forName( OUString::createFromAscii("[]ModuleA.StructA") )->createObject(aAny); + + TEST_ENSHURE(aAny.getValueTypeName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("[]ModuleA.StructA")), "test_RegCoreReflection(): error 54"); + xRefl->forName(OUString::createFromAscii("[][]ModuleA.StructA"))->createObject(aAny); + + TEST_ENSHURE(aAny.getValueTypeName().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("[][]ModuleA.StructA") ), "test_RegCoreReflection(): error 56"); + +// xClass = xRefl->forName(OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.beans.XIntroTest") )); + +// TEST_ENSHURE(xClass.is(), "test_RegCoreReflection(): error 58"); +// TEST_ENSHURE(xClass->getMethod(OUString::createFromAscii("getStrings"))->getReturnType()->getTypeClass() == TypeClass_SEQUENCE, "test_RegCoreReflection(): error 59"); +// TEST_ENSHURE(xClass->getMethod(OUString::createFromAscii("getStrings"))->getReturnType()->getComponentType()->getName() == OUString::createFromAscii("string"), "test_RegCoreReflection(): error 60"); + +// xClass->getMethod(OUString::createFromAscii("getStrings"))->getReturnType()->createObject(aAny); +// TEST_ENSHURE(aAny.getValueTypeName().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("[]string") ), "test_RegCoreReflection(): error 61"); + + TEST_ENSHURE(xRefl->forName(OUString::createFromAscii("[][][]unsigned long"))->getComponentType()->getComponentType()->getComponentType()->getTypeClass() == TypeClass_UNSIGNED_LONG, "test_RegCoreReflection(): error 62"); + + try + { + fprintf( stderr, "%1\n" ); + Any bla = xRefl->forName(OUString::createFromAscii("ModuleA.StructC"))->getField(OUString::createFromAscii("aString"))->get(Any()); + TEST_ENSHURE(sal_False, "test_RegCoreReflection(): error 63"); + return sal_False; + } + catch (IllegalArgumentException &) + { + } + + try + { + fprintf( stderr, "%2\n" ); + Any blup; + blup <<= aStructC; + Any gulp; + rField = Reference< XIdlField2 > ( xRefl->forName(OUString::createFromAscii("ModuleA.StructC"))->getField(OUString::createFromAscii("aString")) , UNO_QUERY); + rField->set( blup, gulp); +// xRefl->forName(OUString::createFromAscii("ModuleA.StructC"))->getField(OUString::createFromAscii("aString"))->set(blup, gulp); + TEST_ENSHURE(sal_False, "test_RegCoreReflection(): error 64"); + return sal_False; + } + catch (IllegalArgumentException &) + { + } + + try + { + fprintf( stderr, "%3\n" ); + Any gulp; + gulp <<= 3.14f; + Any blup; + blup <<= aStructC; + rField = Reference< XIdlField2 > ( + xRefl->forName(OUString::createFromAscii("ModuleA.StructC"))->getField(OUString::createFromAscii("aString")) , UNO_QUERY); + xRefl->forName(OUString::createFromAscii("ModuleA.StructC"))->getField(OUString::createFromAscii("aString"))->set(blup, gulp); + TEST_ENSHURE(sal_False, "test_RegCoreReflection(): error 65"); + return sal_False; + } + catch (IllegalArgumentException &) + { + } + + Any gulp; + gulp <<= OUString(OUString::createFromAscii("Test")); + Any blup; + blup <<= aStructC; + xRefl->forName(OUString::createFromAscii("ModuleA.StructC"))->getField(OUString::createFromAscii("aString"))->set(blup, gulp); + + Reference< XInterfaceA > xAI = new OInterfaceA(); + + try + { + Sequence< Any > params; + fprintf( stderr, "%4\n" ); + + Any a; + a <<= xAI; + Any bla = xRefl->forName(OUString::createFromAscii("ModuleC.XInterfaceA"))->getMethod(OUString::createFromAscii("methodC"))->invoke(a, params); + TEST_ENSHURE(sal_False, "test_RegCoreReflection(): error 66"); + return sal_False; + } + catch (IllegalArgumentException &) + { + } + + StructA aStructA; + + { + Sequence< Any > params(2); + + params.getArray()[0].setValue(&aStructC, ::getCppuType( (const StructC *)0 )); + params.getArray()[1].setValue(&aStructC, ::getCppuType( (const StructC *)0 )); + + Any a; + a <<= xAI; + Any bla = xRefl->forName(OUString::createFromAscii("ModuleC.XInterfaceA"))->getMethod(OUString::createFromAscii("methodC"))->invoke(a, params); + } + try + { + Sequence< Any > params(2); + + params.getArray()[0].setValue(&aStructA, ::getCppuType( (const StructA *)0 )); + params.getArray()[1].setValue(&aStructA, ::getCppuType( (const StructA *)0 )); + + Any a; + a <<= xAI; + Any bla = xRefl->forName(OUString::createFromAscii("ModuleC.XInterfaceA"))->getMethod(OUString::createFromAscii("methodC"))->invoke(a, params); + TEST_ENSHURE(sal_False, "test_RegCoreReflection(): error 67"); + return sal_False; + } + catch (IllegalArgumentException &) + { + } + + Sequence< Any > params(2); + + params.getArray()[0].setValue(&aStructC, ::getCppuType( (const StructC *)0 )); + params.getArray()[1].setValue(&aStructA, ::getCppuType( (const StructA *)0 )); + + Any a; + a <<= xAI; + TEST_ENSHURE(xRefl->forName(OUString::createFromAscii("ModuleC.XInterfaceA"))->getMethod(OUString::createFromAscii("methodC"))->invoke(a, params).getValueType() + == ::getCppuType( (const Sequence<StructB> *)0 ), "test_RegCoreReflection(): error 68"); + + return sal_True; +} + +SAL_IMPLEMENT_MAIN() +{ + sal_Bool bSucc = sal_False; + try + { + OUString aLibName( RTL_CONSTASCII_USTRINGPARAM( + "reflection.uno" SAL_DLLEXTENSION) ); + + Reference< XMultiServiceFactory > xMgr( + createRegistryServiceFactory( + OUString( RTL_CONSTASCII_USTRINGPARAM("stoctest.rdb") ) ) ); + Reference< XComponentContext > xContext; + Reference< beans::XPropertySet > xProps( xMgr, UNO_QUERY ); + OSL_ASSERT( xProps.is() ); + xProps->getPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= + xContext; + OSL_ASSERT( xContext.is() ); + + Reference< XIdlReflection > xRefl; + xContext->getValueByName( + OUString( + RTL_CONSTASCII_USTRINGPARAM( + "/singletons/com.sun.star.reflection.theCoreReflection")) ) + >>= xRefl; + OSL_ENSURE( + xRefl.is(), "### CoreReflection singleton not accessable!?" ); + + bSucc = test_corefl( xRefl ); + + Reference< XComponent >( xContext, UNO_QUERY )->dispose(); + } + catch (Exception & rExc) + { + OSL_ENSURE( sal_False, "### exception occured!" ); + OString aMsg( + OUStringToOString( rExc.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( "### exception occured: " ); + OSL_TRACE( aMsg.getStr() ); + OSL_TRACE( "\n" ); + } + + printf( "testcorefl %s !\n", (bSucc ? "succeeded" : "failed") ); + return (bSucc ? 0 : -1); +} diff --git a/stoc/test/testcorefl.idl b/stoc/test/testcorefl.idl new file mode 100644 index 000000000000..1ae37a6f45e9 --- /dev/null +++ b/stoc/test/testcorefl.idl @@ -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. + * + ************************************************************************/ +#include <com/sun/star/uno/XInterface.idl> + +module ModuleA +{ + exception ExceptionA + { + boolean aBoolean; + }; + + struct StructA + { + long aLong; + short aShort; + }; + + struct StructB : StructA + { + double aDouble; + float aFloat; + }; + + struct StructC : StructB + { + string aString; + sequence<com::sun::star::uno::XInterface> aInterfaceSeq; + }; + + exception ExceptionB : ExceptionA + { + StructC aStructC; + }; + + interface XInterface1 : com::sun::star::uno::XInterface + { + }; + + exception ExceptionC : ExceptionB + { + XInterface1 aInterface1; + }; + + module ModuleB + { + enum EnumA { VAL_1, VAL_2, VAL_3 = 17}; + }; + +}; + +module ModuleC +{ + const boolean aConstBoolean = True; + const byte aConstByte = 0; + const short aConstShort = -1; + const unsigned short aConstUShort = 1; + const long aConstLong = -2; + const unsigned long aConstULong = 2; +// const hyper aConstHyper = -3; +// const unsigned hyper aConstUHyper = 3; + const float aConstFloat = 3.14; + const double aConstDouble = 3.14e-10; + + + interface XInterfaceA : com::sun::star::uno::XInterface + { + void methodA(); + [oneway] void methodB([in] short aShort); + sequence<ModuleA::StructB> methodC([in] ModuleA::StructC aStructC, [inout] ModuleA::StructA aStructA); + }; + + interface XInterfaceB : XInterfaceA + { + [attribute] string aString; + + XInterfaceA methodD([in] ModuleA::ModuleB::EnumA aEnumA) raises (ModuleA::ExceptionA, ModuleA::ExceptionB, ModuleA::ExceptionC); + }; +}; diff --git a/stoc/test/testiadapter.cxx b/stoc/test/testiadapter.cxx new file mode 100644 index 000000000000..62c9736aa204 --- /dev/null +++ b/stoc/test/testiadapter.cxx @@ -0,0 +1,1069 @@ +/************************************************************************* + * + * 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 <stdio.h> + +#include <sal/main.h> +#include <osl/diagnose.h> + +#include <cppuhelper/servicefactory.hxx> +#include <cppuhelper/weak.hxx> + +#include <test/XLanguageBindingTest.hpp> +#include <com/sun/star/registry/XSimpleRegistry.hpp> +#include <com/sun/star/registry/XImplementationRegistration.hpp> +#include <com/sun/star/script/XInvocation.hpp> +#include <com/sun/star/script/XInvocationAdapterFactory.hpp> +#include <com/sun/star/script/XInvocationAdapterFactory2.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> + +#include <cppuhelper/implbase1.hxx> + + +using namespace test; +using namespace rtl; +using namespace cppu; +using namespace osl; +using namespace com::sun::star::uno; +using namespace com::sun::star::script; +using namespace com::sun::star::beans; +using namespace com::sun::star::lang; +using namespace com::sun::star::reflection; +using namespace com::sun::star::lang; +using namespace com::sun::star::registry; + + +//================================================================================================== +sal_Bool equals( const test::TestElement & rData1, const test::TestElement & rData2 ) +{ + OSL_ENSURE( rData1.Bool == rData2.Bool, "### bool does not match!" ); + OSL_ENSURE( rData1.Char == rData2.Char, "### char does not match!" ); + OSL_ENSURE( rData1.Byte == rData2.Byte, "### byte does not match!" ); + OSL_ENSURE( rData1.Short == rData2.Short, "### short does not match!" ); + OSL_ENSURE( rData1.UShort == rData2.UShort, "### unsigned short does not match!" ); + OSL_ENSURE( rData1.Long == rData2.Long, "### long does not match!" ); + OSL_ENSURE( rData1.ULong == rData2.ULong, "### unsigned long does not match!" ); + OSL_ENSURE( rData1.Hyper == rData2.Hyper, "### hyper does not match!" ); + OSL_ENSURE( rData1.UHyper == rData2.UHyper, "### unsigned hyper does not match!" ); + OSL_ENSURE( rData1.Float == rData2.Float, "### float does not match!" ); + OSL_ENSURE( rData1.Double == rData2.Double, "### double does not match!" ); + OSL_ENSURE( rData1.Enum == rData2.Enum, "### enum does not match!" ); + OSL_ENSURE( rData1.String == rData2.String, "### string does not match!" ); + OSL_ENSURE( rData1.Interface == rData2.Interface, "### interface does not match!" ); + OSL_ENSURE( rData1.Any == rData2.Any, "### any does not match!" ); + + return (rData1.Bool == rData2.Bool && + rData1.Char == rData2.Char && + rData1.Byte == rData2.Byte && + rData1.Short == rData2.Short && + rData1.UShort == rData2.UShort && + rData1.Long == rData2.Long && + rData1.ULong == rData2.ULong && + rData1.Hyper == rData2.Hyper && + rData1.UHyper == rData2.UHyper && + rData1.Float == rData2.Float && + rData1.Double == rData2.Double && + rData1.Enum == rData2.Enum && + rData1.String == rData2.String && + rData1.Interface == rData2.Interface && + rData1.Any == rData2.Any); +} +//================================================================================================== +sal_Bool equals( const test::TestData & rData1, const test::TestData & rData2 ) +{ + sal_Int32 nLen; + + if ((rData1.Sequence == rData2.Sequence) && + equals( (const test::TestElement &)rData1, (const test::TestElement &)rData2 ) && + (nLen = rData1.Sequence.getLength()) == rData2.Sequence.getLength()) + { + // once again by hand sequence == + const test::TestElement * pElements1 = rData1.Sequence.getConstArray(); + const test::TestElement * pElements2 = rData2.Sequence.getConstArray(); + for ( ; nLen--; ) + { + if (! equals( pElements1[nLen], pElements2[nLen] )) + { + OSL_ENSURE( sal_False, "### sequence element did not match!" ); + return sal_False; + } + } + return sal_True; + } + return sal_False; +} +//================================================================================================== +void assign( test::TestElement & rData, + sal_Bool bBool, sal_Unicode cChar, sal_Int8 nByte, + sal_Int16 nShort, sal_uInt16 nUShort, + sal_Int32 nLong, sal_uInt32 nULong, + sal_Int64 nHyper, sal_uInt64 nUHyper, + float fFloat, double fDouble, + test::TestEnum eEnum, const ::rtl::OUString& rStr, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& xTest, + const ::com::sun::star::uno::Any& rAny ) +{ + rData.Bool = bBool; + rData.Char = cChar; + rData.Byte = nByte; + rData.Short = nShort; + rData.UShort = nUShort; + rData.Long = nLong; + rData.ULong = nULong; + rData.Hyper = nHyper; + rData.UHyper = nUHyper; + rData.Float = fFloat; + rData.Double = fDouble; + rData.Enum = eEnum; + rData.String = rStr; + rData.Interface = xTest; + rData.Any = rAny; +} +//================================================================================================== +void assign( test::TestData & rData, + sal_Bool bBool, sal_Unicode cChar, sal_Int8 nByte, + sal_Int16 nShort, sal_uInt16 nUShort, + sal_Int32 nLong, sal_uInt32 nULong, + sal_Int64 nHyper, sal_uInt64 nUHyper, + float fFloat, double fDouble, + test::TestEnum eEnum, const ::rtl::OUString& rStr, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& xTest, + const ::com::sun::star::uno::Any& rAny, + const com::sun::star::uno::Sequence< test::TestElement >& rSequence ) +{ + assign( (test::TestElement &)rData, + bBool, cChar, nByte, nShort, nUShort, nLong, nULong, nHyper, nUHyper, fFloat, fDouble, + eEnum, rStr, xTest, rAny ); + rData.Sequence = rSequence; +} + +//================================================================================================== +class Test_Impl : public WeakImplHelper1< XLanguageBindingTest > +{ + test::TestData _aData, _aStructData; + +public: + virtual ~Test_Impl() + { OSL_TRACE( "> scalar Test_Impl dtor <\n" ); } + + // XLBTestBase + virtual void SAL_CALL setValues( sal_Bool bBool, sal_Unicode cChar, sal_Int8 nByte, + sal_Int16 nShort, sal_uInt16 nUShort, + sal_Int32 nLong, sal_uInt32 nULong, + sal_Int64 nHyper, sal_uInt64 nUHyper, + float fFloat, double fDouble, + test::TestEnum eEnum, const ::rtl::OUString& rStr, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& xTest, + const ::com::sun::star::uno::Any& rAny, + const ::com::sun::star::uno::Sequence<test::TestElement >& rSequence, + const test::TestData& rStruct ) + throw(com::sun::star::uno::RuntimeException); + + virtual test::TestData SAL_CALL setValues2( sal_Bool& bBool, sal_Unicode& cChar, sal_Int8& nByte, + sal_Int16& nShort, sal_uInt16& nUShort, + sal_Int32& nLong, sal_uInt32& nULong, + sal_Int64& nHyper, sal_uInt64& nUHyper, + float& fFloat, double& fDouble, + test::TestEnum& eEnum, rtl::OUString& rStr, + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& xTest, + ::com::sun::star::uno::Any& rAny, + ::com::sun::star::uno::Sequence<test::TestElement >& rSequence, + test::TestData& rStruct ) + throw(com::sun::star::uno::RuntimeException); + + virtual test::TestData SAL_CALL getValues( sal_Bool& bBool, sal_Unicode& cChar, sal_Int8& nByte, + sal_Int16& nShort, sal_uInt16& nUShort, + sal_Int32& nLong, sal_uInt32& nULong, + sal_Int64& nHyper, sal_uInt64& nUHyper, + float& fFloat, double& fDouble, + test::TestEnum& eEnum, rtl::OUString& rStr, + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& xTest, + ::com::sun::star::uno::Any& rAny, + ::com::sun::star::uno::Sequence< test::TestElement >& rSequence, + test::TestData& rStruct ) + throw(com::sun::star::uno::RuntimeException); + + virtual sal_Bool SAL_CALL getBool() throw(com::sun::star::uno::RuntimeException) + { return _aData.Bool; } + virtual sal_Int8 SAL_CALL getByte() throw(com::sun::star::uno::RuntimeException) + { return _aData.Byte; } + virtual sal_Unicode SAL_CALL getChar() throw(com::sun::star::uno::RuntimeException) + { return _aData.Char; } + virtual sal_Int16 SAL_CALL getShort() throw(com::sun::star::uno::RuntimeException) + { return _aData.Short; } + virtual sal_uInt16 SAL_CALL getUShort() throw(com::sun::star::uno::RuntimeException) + { return _aData.UShort; } + virtual sal_Int32 SAL_CALL getLong() throw(com::sun::star::uno::RuntimeException) + { return _aData.Long; } + virtual sal_uInt32 SAL_CALL getULong() throw(com::sun::star::uno::RuntimeException) + { return _aData.ULong; } + virtual sal_Int64 SAL_CALL getHyper() throw(com::sun::star::uno::RuntimeException) + { return _aData.Hyper; } + virtual sal_uInt64 SAL_CALL getUHyper() throw(com::sun::star::uno::RuntimeException) + { return _aData.UHyper; } + virtual float SAL_CALL getFloat() throw(com::sun::star::uno::RuntimeException) + { return _aData.Float; } + virtual double SAL_CALL getDouble() throw(com::sun::star::uno::RuntimeException) + { return _aData.Double; } + virtual test::TestEnum SAL_CALL getEnum() throw(com::sun::star::uno::RuntimeException) + { return _aData.Enum; } + virtual rtl::OUString SAL_CALL getString() throw(com::sun::star::uno::RuntimeException) + { return _aData.String; } + virtual com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL getInterface( ) throw(com::sun::star::uno::RuntimeException) + { return _aData.Interface; } + virtual com::sun::star::uno::Any SAL_CALL getAny() throw(com::sun::star::uno::RuntimeException) + { return _aData.Any; } + virtual com::sun::star::uno::Sequence< test::TestElement > SAL_CALL getSequence() throw(com::sun::star::uno::RuntimeException) + { return _aData.Sequence; } + virtual test::TestData SAL_CALL getStruct() throw(com::sun::star::uno::RuntimeException) + { return _aStructData; } + + virtual void SAL_CALL setBool( sal_Bool _bool ) throw(::com::sun::star::uno::RuntimeException) + { _aData.Bool = _bool; } + virtual void SAL_CALL setByte( sal_Int8 _byte ) throw(::com::sun::star::uno::RuntimeException) + { _aData.Byte = _byte; } + virtual void SAL_CALL setChar( sal_Unicode _char ) throw(::com::sun::star::uno::RuntimeException) + { _aData.Char = _char; } + virtual void SAL_CALL setShort( sal_Int16 _short ) throw(::com::sun::star::uno::RuntimeException) + { _aData.Short = _short; } + virtual void SAL_CALL setUShort( sal_uInt16 _ushort ) throw(::com::sun::star::uno::RuntimeException) + { _aData.UShort = _ushort; } + virtual void SAL_CALL setLong( sal_Int32 _long ) throw(::com::sun::star::uno::RuntimeException) + { _aData.Long = _long; } + virtual void SAL_CALL setULong( sal_uInt32 _ulong ) throw(::com::sun::star::uno::RuntimeException) + { _aData.ULong = _ulong; } + virtual void SAL_CALL setHyper( sal_Int64 _hyper ) throw(::com::sun::star::uno::RuntimeException) + { _aData.Hyper = _hyper; } + virtual void SAL_CALL setUHyper( sal_uInt64 _uhyper ) throw(::com::sun::star::uno::RuntimeException) + { _aData.UHyper = _uhyper; } + virtual void SAL_CALL setFloat( float _float ) throw(::com::sun::star::uno::RuntimeException) + { _aData.Float = _float; } + virtual void SAL_CALL setDouble( double _double ) throw(::com::sun::star::uno::RuntimeException) + { _aData.Double = _double; } + virtual void SAL_CALL setEnum( test::TestEnum _enum ) throw(::com::sun::star::uno::RuntimeException) + { _aData.Enum = _enum; } + virtual void SAL_CALL setString( const ::rtl::OUString& _string ) throw(::com::sun::star::uno::RuntimeException) + { _aData.String = _string; } + virtual void SAL_CALL setInterface( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _interface ) throw(::com::sun::star::uno::RuntimeException) + { _aData.Interface = _interface; } + virtual void SAL_CALL setAny( const ::com::sun::star::uno::Any& _any ) throw(::com::sun::star::uno::RuntimeException) + { _aData.Any = _any; } + virtual void SAL_CALL setSequence( const ::com::sun::star::uno::Sequence<test::TestElement >& _sequence ) throw(::com::sun::star::uno::RuntimeException) + { _aData.Sequence = _sequence; } + virtual void SAL_CALL setStruct( const test::TestData& _struct ) throw(::com::sun::star::uno::RuntimeException) + { _aStructData = _struct; } + + // XLanguageBindingTest + virtual test::TestData SAL_CALL raiseException( sal_Bool& bBool, sal_Unicode& cChar, sal_Int8& nByte, sal_Int16& nShort, sal_uInt16& nUShort, sal_Int32& nLong, sal_uInt32& nULong, sal_Int64& nHyper, sal_uInt64& nUHyper, float& fFloat, double& fDouble, test::TestEnum& eEnum, ::rtl::OUString& aString, ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& xInterface, ::com::sun::star::uno::Any& aAny, ::com::sun::star::uno::Sequence<test::TestElement >& aSequence,test::TestData& aStruct ) + throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + virtual sal_Int32 SAL_CALL getRuntimeException() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setRuntimeException( sal_Int32 _runtimeexception ) throw(::com::sun::star::uno::RuntimeException); +}; +//================================================================================================== +class XLB_Invocation : public WeakImplHelper1< XInvocation > +{ + Reference< XLanguageBindingTest > _xLBT; + +public: + XLB_Invocation( const Reference< XMultiServiceFactory > & /*xMgr*/, + const Reference< XLanguageBindingTest > & xLBT ) + : _xLBT( xLBT ) + {} + + // XInvocation + virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection() throw(::com::sun::star::uno::RuntimeException) + { return Reference< XIntrospectionAccess >(); } + virtual Any SAL_CALL invoke( const OUString & rFunctionName, + const Sequence< Any > & rParams, + Sequence< sal_Int16 > & rOutParamIndex, + Sequence< Any > & rOutParam ) throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::script::CannotConvertException, ::com::sun::star::reflection::InvocationTargetException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setValue( const OUString & rPropertyName, const Any & rValue ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::script::CannotConvertException, ::com::sun::star::reflection::InvocationTargetException, ::com::sun::star::uno::RuntimeException); + virtual Any SAL_CALL getValue( const OUString & rPropertyName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasMethod( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL hasProperty( const OUString & rName ) throw(::com::sun::star::uno::RuntimeException); +}; +//__________________________________________________________________________________________________ +Any XLB_Invocation::invoke( const OUString & rFunctionName, + const Sequence< Any > & rParams, + Sequence< sal_Int16 > & rOutParamIndex, + Sequence< Any > & rOutParam ) + throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::script::CannotConvertException, ::com::sun::star::reflection::InvocationTargetException, ::com::sun::star::uno::RuntimeException) +{ + bool bImplementedMethod = true; + + Any aRet; + + OSL_ASSERT( rOutParam.getLength() == 0 ); + OSL_ASSERT( rOutParamIndex.getLength() == 0 ); + + try + { + sal_Bool aBool; + sal_Unicode aChar; + sal_Int8 nByte; + sal_Int16 nShort; + sal_uInt16 nUShort; + sal_Int32 nLong; + sal_uInt32 nULong; + sal_Int64 nHyper; + sal_uInt64 nUHyper; + float fFloat; + double fDouble; + TestEnum eEnum; + OUString aString; + Reference< XInterface > xInterface; + Any aAny; + Sequence< TestElement > aSeq; + TestData aData; + + if (rFunctionName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("setValues") )) + { + OSL_ASSERT( rParams.getLength() == 17 ); + aBool = *(sal_Bool *)rParams[0].getValue(); + aChar = *(sal_Unicode *)rParams[1].getValue(); + rParams[2] >>= nByte; + rParams[3] >>= nShort; + rParams[4] >>= nUShort; + rParams[5] >>= nLong; + rParams[6] >>= nULong; + rParams[7] >>= nHyper; + rParams[8] >>= nUHyper; + rParams[9] >>= fFloat; + rParams[10] >>= fDouble; + rParams[11] >>= eEnum; + rParams[12] >>= aString; + rParams[13] >>= xInterface; + rParams[14] >>= aAny; + rParams[15] >>= aSeq; + rParams[16] >>= aData; + + _xLBT->setValues( aBool, aChar, nByte, nShort, nUShort, nLong, nULong, + nHyper, nUHyper, fFloat, fDouble, eEnum, aString, xInterface, + aAny, aSeq, aData ); + + rOutParamIndex.realloc( 0 ); + rOutParam.realloc( 0 ); + } + else if (rFunctionName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("setValues2") )) + { + aBool = *(sal_Bool *)rParams[0].getValue(); + aChar = *(sal_Unicode *)rParams[1].getValue(); + rParams[2] >>= nByte; + rParams[3] >>= nShort; + rParams[4] >>= nUShort; + rParams[5] >>= nLong; + rParams[6] >>= nULong; + rParams[7] >>= nHyper; + rParams[8] >>= nUHyper; + rParams[9] >>= fFloat; + rParams[10] >>= fDouble; + rParams[11] >>= eEnum; + rParams[12] >>= aString; + rParams[13] >>= xInterface; + rParams[14] >>= aAny; + rParams[15] >>= aSeq; + rParams[16] >>= aData; + + aRet <<= _xLBT->setValues2( aBool, aChar, nByte, nShort, nUShort, nLong, nULong, + nHyper, nUHyper, fFloat, fDouble, eEnum, aString, xInterface, + aAny, aSeq, aData ); + + rOutParamIndex.realloc( 17 ); + rOutParamIndex[0] = 0; + rOutParamIndex[1] = 1; + rOutParamIndex[2] = 2; + rOutParamIndex[3] = 3; + rOutParamIndex[4] = 4; + rOutParamIndex[5] = 5; + rOutParamIndex[6] = 6; + rOutParamIndex[7] = 7; + rOutParamIndex[8] = 8; + rOutParamIndex[9] = 9; + rOutParamIndex[10] = 10; + rOutParamIndex[11] = 11; + rOutParamIndex[12] = 12; + rOutParamIndex[13] = 13; + rOutParamIndex[14] = 14; + rOutParamIndex[15] = 15; + rOutParamIndex[16] = 16; + + rOutParam.realloc( 17 ); + rOutParam[0].setValue( &aBool, ::getCppuBooleanType() ); + rOutParam[1].setValue( &aChar, ::getCppuCharType() ); + rOutParam[2] <<= nByte; + rOutParam[3] <<= nShort; + rOutParam[4] <<= nUShort; + rOutParam[5] <<= nLong; + rOutParam[6] <<= nULong; + rOutParam[7] <<= nHyper; + rOutParam[8] <<= nUHyper; + rOutParam[9] <<= fFloat; + rOutParam[10] <<= fDouble; + rOutParam[11] <<= eEnum; + rOutParam[12] <<= aString; + rOutParam[13] <<= xInterface; + rOutParam[14] <<= aAny; + rOutParam[15] <<= aSeq; + rOutParam[16] <<= aData; + } + else if (rFunctionName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("getValues") )) + { + aRet <<= _xLBT->getValues( aBool, aChar, nByte, nShort, nUShort, nLong, nULong, + nHyper, nUHyper, fFloat, fDouble, eEnum, aString, xInterface, + aAny, aSeq, aData ); + + rOutParamIndex.realloc( 17 ); + rOutParamIndex[0] = 0; + rOutParamIndex[1] = 1; + rOutParamIndex[2] = 2; + rOutParamIndex[3] = 3; + rOutParamIndex[4] = 4; + rOutParamIndex[5] = 5; + rOutParamIndex[6] = 6; + rOutParamIndex[7] = 7; + rOutParamIndex[8] = 8; + rOutParamIndex[9] = 9; + rOutParamIndex[10] = 10; + rOutParamIndex[11] = 11; + rOutParamIndex[12] = 12; + rOutParamIndex[13] = 13; + rOutParamIndex[14] = 14; + rOutParamIndex[15] = 15; + rOutParamIndex[16] = 16; + + rOutParam.realloc( 17 ); + rOutParam[0].setValue( &aBool, ::getCppuBooleanType() ); + rOutParam[1].setValue( &aChar, ::getCppuCharType() ); + rOutParam[2] <<= nByte; + rOutParam[3] <<= nShort; + rOutParam[4] <<= nUShort; + rOutParam[5] <<= nLong; + rOutParam[6] <<= nULong; + rOutParam[7] <<= nHyper; + rOutParam[8] <<= nUHyper; + rOutParam[9] <<= fFloat; + rOutParam[10] <<= fDouble; + rOutParam[11] <<= eEnum; + rOutParam[12] <<= aString; + rOutParam[13] <<= xInterface; + rOutParam[14] <<= aAny; + rOutParam[15] <<= aSeq; + rOutParam[16] <<= aData; + } + else if (rFunctionName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("raiseException") )) + { + aRet <<= _xLBT->raiseException( aBool, aChar, nByte, nShort, nUShort, nLong, nULong, + nHyper, nUHyper, fFloat, fDouble, eEnum, aString, xInterface, + aAny, aSeq, aData ); + + rOutParamIndex.realloc( 17 ); + rOutParamIndex[0] = 0; + rOutParamIndex[1] = 1; + rOutParamIndex[2] = 2; + rOutParamIndex[3] = 3; + rOutParamIndex[4] = 4; + rOutParamIndex[5] = 5; + rOutParamIndex[6] = 6; + rOutParamIndex[7] = 7; + rOutParamIndex[8] = 8; + rOutParamIndex[9] = 9; + rOutParamIndex[10] = 10; + rOutParamIndex[11] = 11; + rOutParamIndex[12] = 12; + rOutParamIndex[13] = 13; + rOutParamIndex[14] = 14; + rOutParamIndex[15] = 15; + rOutParamIndex[16] = 16; + + rOutParam.realloc( 17 ); + rOutParam[0].setValue( &aBool, ::getCppuBooleanType() ); + rOutParam[1].setValue( &aChar, ::getCppuCharType() ); + rOutParam[2] <<= nByte; + rOutParam[3] <<= nShort; + rOutParam[4] <<= nUShort; + rOutParam[5] <<= nLong; + rOutParam[6] <<= nULong; + rOutParam[7] <<= nHyper; + rOutParam[8] <<= nUHyper; + rOutParam[9] <<= fFloat; + rOutParam[10] <<= fDouble; + rOutParam[11] <<= eEnum; + rOutParam[12] <<= aString; + rOutParam[13] <<= xInterface; + rOutParam[14] <<= aAny; + rOutParam[15] <<= aSeq; + rOutParam[16] <<= aData; + } + else + { + bImplementedMethod = false; + } + } + catch (IllegalArgumentException & rExc) + { + // thrown by raiseException() call + InvocationTargetException aExc; + aExc.TargetException <<= rExc; + throw aExc; + } + catch (Exception &) + { + OSL_ENSURE( sal_False, "### unexpected exception caught!" ); + throw; + } + + if (! bImplementedMethod) + { + throw IllegalArgumentException( + OUString( RTL_CONSTASCII_USTRINGPARAM("not an implemented method!") ), + (OWeakObject *)this, 0 ); + } + + return aRet; +} +//__________________________________________________________________________________________________ +void XLB_Invocation::setValue( const OUString & rName, const Any & rValue ) + throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::script::CannotConvertException, ::com::sun::star::reflection::InvocationTargetException, ::com::sun::star::uno::RuntimeException) +{ + if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Bool") )) + _xLBT->setBool( *(const sal_Bool *)rValue.getValue() ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Byte") )) + _xLBT->setByte( *(const sal_Int8 *)rValue.getValue() ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Char") )) + _xLBT->setChar( *(const sal_Unicode *)rValue.getValue() ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Short") )) + _xLBT->setShort( *(const sal_Int16 *)rValue.getValue() ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("UShort") )) + _xLBT->setUShort( *(const sal_uInt16 *)rValue.getValue() ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Long") )) + _xLBT->setLong( *(const sal_Int32 *)rValue.getValue() ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("ULong") )) + _xLBT->setULong( *(const sal_uInt32 *)rValue.getValue() ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Hyper") )) + _xLBT->setHyper( *(const sal_Int64 *)rValue.getValue() ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("UHyper") )) + _xLBT->setUHyper( *(const sal_uInt64 *)rValue.getValue() ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Float") )) + _xLBT->setFloat( *(const float *)rValue.getValue() ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Double") )) + _xLBT->setDouble( *(const double *)rValue.getValue() ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Enum") )) + _xLBT->setEnum( *(const TestEnum *)rValue.getValue() ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("String") )) + _xLBT->setString( *(const OUString *)rValue.getValue() ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Interface") )) + _xLBT->setInterface( *(const Reference< XInterface > *)rValue.getValue() ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Any") )) + _xLBT->setAny( rValue ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Sequence") )) + _xLBT->setSequence( *(const Sequence< TestElement > *)rValue.getValue() ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Struct") )) + _xLBT->setStruct( *(const TestData *)rValue.getValue() ); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("RuntimeException") )) + _xLBT->setRuntimeException( *(const sal_Int32 *)rValue.getValue() ); +} +//__________________________________________________________________________________________________ +Any XLB_Invocation::getValue( const OUString & rName ) + throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException) +{ + Any aRet; + if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Bool") )) + { + sal_Bool aBool = _xLBT->getBool(); + aRet.setValue( &aBool, ::getCppuBooleanType() ); + } + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Byte") )) + aRet <<= _xLBT->getByte(); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Char") )) + { + sal_Unicode aChar = _xLBT->getChar(); + aRet.setValue( &aChar, ::getCppuCharType() ); + } + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Short") )) + aRet <<= _xLBT->getShort(); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("UShort") )) + aRet <<= _xLBT->getUShort(); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Long") )) + aRet <<= _xLBT->getLong(); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("ULong") )) + aRet <<= _xLBT->getULong(); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Hyper") )) + aRet <<= _xLBT->getHyper(); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("UHyper") )) + aRet <<= _xLBT->getUHyper(); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Float") )) + aRet <<= _xLBT->getFloat(); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Double") )) + aRet <<= _xLBT->getDouble(); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Enum") )) + aRet <<= _xLBT->getEnum(); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("String") )) + aRet <<= _xLBT->getString(); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Interface") )) + aRet <<= _xLBT->getInterface(); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Any") )) + aRet <<= _xLBT->getAny(); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Sequence") )) + aRet <<= _xLBT->getSequence(); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Struct") )) + aRet <<= _xLBT->getStruct(); + else if (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("RuntimeException") )) + aRet <<= _xLBT->getRuntimeException(); + return aRet; +} +//__________________________________________________________________________________________________ +sal_Bool XLB_Invocation::hasMethod( const OUString & rName ) + throw(::com::sun::star::uno::RuntimeException) +{ + return (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("raiseException") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("getValues") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("setValues2") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("setValues") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("acquire") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("release") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("queryInterface") )); +} +//__________________________________________________________________________________________________ +sal_Bool XLB_Invocation::hasProperty( const OUString & rName ) + throw(::com::sun::star::uno::RuntimeException) +{ + return (rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Bool") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Byte") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Char") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Short") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("UShort") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Long") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("ULong") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Hyper") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("UHyper") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Float") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Double") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Enum") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("String") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Interface") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Any") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Sequence") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("Struct") ) || + rName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("RuntimeException") ) ); +} + +//################################################################################################## + +//__________________________________________________________________________________________________ +void Test_Impl::setValues( sal_Bool bBool, sal_Unicode cChar, sal_Int8 nByte, + sal_Int16 nShort, sal_uInt16 nUShort, + sal_Int32 nLong, sal_uInt32 nULong, + sal_Int64 nHyper, sal_uInt64 nUHyper, + float fFloat, double fDouble, + test::TestEnum eEnum, const ::rtl::OUString& rStr, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& xTest, + const ::com::sun::star::uno::Any& rAny, + const ::com::sun::star::uno::Sequence<test::TestElement >& rSequence, + const test::TestData& rStruct ) + throw(com::sun::star::uno::RuntimeException) +{ + assign( _aData, + bBool, cChar, nByte, nShort, nUShort, nLong, nULong, nHyper, nUHyper, fFloat, fDouble, + eEnum, rStr, xTest, rAny, rSequence ); + _aStructData = rStruct; +} +//__________________________________________________________________________________________________ +test::TestData Test_Impl::setValues2( sal_Bool& bBool, sal_Unicode& cChar, sal_Int8& nByte, + sal_Int16& nShort, sal_uInt16& nUShort, + sal_Int32& nLong, sal_uInt32& nULong, + sal_Int64& nHyper, sal_uInt64& nUHyper, + float& fFloat, double& fDouble, + test::TestEnum& eEnum, rtl::OUString& rStr, + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& xTest, + ::com::sun::star::uno::Any& rAny, + ::com::sun::star::uno::Sequence<test::TestElement >& rSequence, + test::TestData& rStruct ) + throw(com::sun::star::uno::RuntimeException) +{ + assign( _aData, + bBool, cChar, nByte, nShort, nUShort, nLong, nULong, nHyper, nUHyper, fFloat, fDouble, + eEnum, rStr, xTest, rAny, rSequence ); + _aStructData = rStruct; + return _aStructData; +} +//__________________________________________________________________________________________________ +test::TestData Test_Impl::getValues( sal_Bool& bBool, sal_Unicode& cChar, sal_Int8& nByte, + sal_Int16& nShort, sal_uInt16& nUShort, + sal_Int32& nLong, sal_uInt32& nULong, + sal_Int64& nHyper, sal_uInt64& nUHyper, + float& fFloat, double& fDouble, + test::TestEnum& eEnum, rtl::OUString& rStr, + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& xTest, + ::com::sun::star::uno::Any& rAny, + ::com::sun::star::uno::Sequence<test::TestElement >& rSequence, + test::TestData& rStruct ) + throw(com::sun::star::uno::RuntimeException) +{ + bBool = _aData.Bool; + cChar = _aData.Char; + nByte = _aData.Byte; + nShort = _aData.Short; + nUShort = _aData.UShort; + nLong = _aData.Long; + nULong = _aData.ULong; + nHyper = _aData.Hyper; + nUHyper = _aData.UHyper; + fFloat = _aData.Float; + fDouble = _aData.Double; + eEnum = _aData.Enum; + rStr = _aData.String; + xTest = _aData.Interface; + rAny = _aData.Any; + rSequence = _aData.Sequence; + rStruct = _aStructData; + return _aStructData; +} + +//================================================================================================== +sal_Bool performTest( const Reference<XLanguageBindingTest > & xLBT ) +{ + OSL_ENSURE( xLBT.is(), "### no test interface!" ); + if (xLBT.is()) + { + // this data is never ever granted access to by calls other than equals(), assign()! + test::TestData aData; // test against this data + + Reference<XInterface > xI( *new OWeakObject() ); + + assign( (test::TestElement &)aData, + sal_True, '@', 17, 0x1234, 0xfedc, 0x12345678, 0xfedcba98, + SAL_CONST_INT64(0x123456789abcdef0), + SAL_CONST_UINT64(0xfedcba9876543210), + (float)17.0815, 3.1415926359, TestEnum_LOLA, OUString::createFromAscii("dumdidum"), xI, + Any( &xI, ::getCppuType( (const Reference<XInterface > *)0 ) ) ); + + OSL_ENSURE( aData.Any == xI, "### unexpected any!" ); + OSL_ENSURE( !(aData.Any != xI), "### unexpected any!" ); + + aData.Sequence = Sequence<test::TestElement >( (const test::TestElement *)&aData, 1 ); + // aData complete + //================================================================================ + + // this is a manually copy of aData for first setting... + test::TestData aSetData; + + assign( (test::TestElement &)aSetData, + aData.Bool, aData.Char, aData.Byte, aData.Short, aData.UShort, + aData.Long, aData.ULong, aData.Hyper, aData.UHyper, aData.Float, aData.Double, + aData.Enum, aData.String, xI, + Any( &xI, ::getCppuType( (const Reference<XInterface > *)0 ) ) ); + + aSetData.Sequence = Sequence<test::TestElement >( (const test::TestElement *)&aSetData, 1 ); + + xLBT->setValues( + aSetData.Bool, aSetData.Char, aSetData.Byte, aSetData.Short, aSetData.UShort, + aSetData.Long, aSetData.ULong, aSetData.Hyper, aSetData.UHyper, aSetData.Float, aSetData.Double, + aSetData.Enum, aSetData.String, aSetData.Interface, aSetData.Any, aSetData.Sequence, aSetData ); + + { + test::TestData aRet, aRet2; + xLBT->getValues( + aRet.Bool, aRet.Char, aRet.Byte, aRet.Short, aRet.UShort, + aRet.Long, aRet.ULong, aRet.Hyper, aRet.UHyper, aRet.Float, aRet.Double, + aRet.Enum, aRet.String, aRet.Interface, aRet.Any, aRet.Sequence, aRet2 ); + + OSL_ASSERT( equals( aData, aRet ) && equals( aData, aRet2 ) ); + + // set last retrieved values + test::TestData aSV2ret = xLBT->setValues2( + aRet.Bool, aRet.Char, aRet.Byte, aRet.Short, aRet.UShort, + aRet.Long, aRet.ULong, aRet.Hyper, aRet.UHyper, aRet.Float, aRet.Double, + aRet.Enum, aRet.String, aRet.Interface, aRet.Any, aRet.Sequence, aRet2 ); + + OSL_ASSERT( equals( aData, aSV2ret ) && equals( aData, aRet2 ) ); + } + { + test::TestData aRet, aRet2; + test::TestData aGVret = xLBT->getValues( + aRet.Bool, aRet.Char, aRet.Byte, aRet.Short, aRet.UShort, + aRet.Long, aRet.ULong, aRet.Hyper, aRet.UHyper, aRet.Float, aRet.Double, + aRet.Enum, aRet.String, aRet.Interface, aRet.Any, aRet.Sequence, aRet2 ); + + OSL_ASSERT( equals( aData, aRet ) && equals( aData, aRet2 ) && equals( aData, aGVret ) ); + + // set last retrieved values + xLBT->setBool( aRet.Bool ); + xLBT->setChar( aRet.Char ); + xLBT->setByte( aRet.Byte ); + xLBT->setShort( aRet.Short ); + xLBT->setUShort( aRet.UShort ); + xLBT->setLong( aRet.Long ); + xLBT->setULong( aRet.ULong ); + xLBT->setHyper( aRet.Hyper ); + xLBT->setUHyper( aRet.UHyper ); + xLBT->setFloat( aRet.Float ); + xLBT->setDouble( aRet.Double ); + xLBT->setEnum( aRet.Enum ); + xLBT->setString( aRet.String ); + xLBT->setInterface( aRet.Interface ); + xLBT->setAny( aRet.Any ); + xLBT->setSequence( aRet.Sequence ); + xLBT->setStruct( aRet2 ); + } + { + test::TestData aRet, aRet2; + aRet.Hyper = xLBT->getHyper(); + aRet.UHyper = xLBT->getUHyper(); + aRet.Float = xLBT->getFloat(); + aRet.Double = xLBT->getDouble(); + aRet.Byte = xLBT->getByte(); + aRet.Char = xLBT->getChar(); + aRet.Bool = xLBT->getBool(); + aRet.Short = xLBT->getShort(); + aRet.UShort = xLBT->getUShort(); + aRet.Long = xLBT->getLong(); + aRet.ULong = xLBT->getULong(); + aRet.Enum = xLBT->getEnum(); + aRet.String = xLBT->getString(); + aRet.Interface = xLBT->getInterface(); + aRet.Any = xLBT->getAny(); + aRet.Sequence = xLBT->getSequence(); + aRet2 = xLBT->getStruct(); + + return (equals( aData, aRet ) && equals( aData, aRet2 )); + } + } + return sal_False; +} + +//__________________________________________________________________________________________________ +test::TestData Test_Impl::raiseException( sal_Bool& /*bBool*/, sal_Unicode& /*cChar*/, sal_Int8& /*nByte*/, sal_Int16& /*nShort*/, sal_uInt16& /*nUShort*/, sal_Int32& /*nLong*/, sal_uInt32& /*nULong*/, sal_Int64& /*nHyper*/, sal_uInt64& /*nUHyper*/, float& /*fFloat*/, double& /*fDouble*/, test::TestEnum& /*eEnum*/, ::rtl::OUString& /*aString*/, ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& /*xInterface*/, ::com::sun::star::uno::Any& /*aAny*/, ::com::sun::star::uno::Sequence< test::TestElement >& /*aSequence*/, test::TestData& /*aStruct*/ ) + throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) +{ + IllegalArgumentException aExc; + aExc.ArgumentPosition = 5; + aExc.Message = OUString::createFromAscii("dum dum dum ich tanz im kreis herum..."); + aExc.Context = *this; + throw aExc; +} +//__________________________________________________________________________________________________ +sal_Int32 Test_Impl::getRuntimeException() throw(::com::sun::star::uno::RuntimeException) +{ + RuntimeException aExc; + aExc.Message = OUString::createFromAscii("dum dum dum ich tanz im kreis herum..."); + aExc.Context = *this; + throw aExc; +} +//__________________________________________________________________________________________________ +void Test_Impl::setRuntimeException( sal_Int32 /*_runtimeexception*/ ) throw(::com::sun::star::uno::RuntimeException) +{ + RuntimeException aExc; + aExc.Message = OUString::createFromAscii("dum dum dum ich tanz im kreis herum..."); + aExc.Context = *this; + throw aExc; +} + +//================================================================================================== +sal_Bool raiseException( const Reference<XLanguageBindingTest > & xLBT ) +{ + try + { + try + { + try + { + test::TestData aRet, aRet2; + xLBT->raiseException( + aRet.Bool, aRet.Char, aRet.Byte, aRet.Short, aRet.UShort, + aRet.Long, aRet.ULong, aRet.Hyper, aRet.UHyper, aRet.Float, aRet.Double, + aRet.Enum, aRet.String, aRet.Interface, aRet.Any, aRet.Sequence, aRet2 ); + return sal_False; + } + catch (IllegalArgumentException aExc) + { + OSL_ENSURE( aExc.ArgumentPosition == 5 && +// aExc.Context == xLBT && + aExc.Message.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dum dum dum ich tanz im kreis herum...")), + "### unexpected exception content!" ); + + Reference<XLanguageBindingTest > xLBT2( + Reference<XLanguageBindingTest >::query( aExc.Context ) ); + + OSL_ENSURE( xLBT2.is(), "### unexpected source of exception!" ); + if (xLBT2.is()) + xLBT2->getRuntimeException(); + else + return sal_False; + } + } + catch (const RuntimeException & rExc) + { + OSL_ENSURE(//rExc.Context == xLBT && + rExc.Message.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dum dum dum ich tanz im kreis herum...")), + "### unexpected exception content!" ); + + Reference<XLanguageBindingTest > xLBT2( + Reference<XLanguageBindingTest >::query( rExc.Context ) ); + + OSL_ENSURE( xLBT2.is(), "### unexpected source of exception!" ); + if (xLBT2.is()) + xLBT2->setRuntimeException( 0xcafebabe ); + else + return sal_False; + } + } + catch (Exception & aExc) + { + OSL_ENSURE( //aExc.Context == xLBT && + aExc.Message.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dum dum dum ich tanz im kreis herum...")), + "### unexpected exception content!" ); + return (//aExc.Context == xLBT && + aExc.Message.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("dum dum dum ich tanz im kreis herum..."))); + } + return sal_False; +} + +//================================================================================================== +static sal_Bool test_adapter( const Reference< XMultiServiceFactory > & xMgr ) +{ + Reference< XInvocationAdapterFactory > xAdapFac( + xMgr->createInstance( OUString::createFromAscii("com.sun.star.script.InvocationAdapterFactory") ), UNO_QUERY ); + Reference< XInvocationAdapterFactory2 > xAdapFac2( xAdapFac, UNO_QUERY_THROW ); + + Reference< XLanguageBindingTest > xOriginal( (XLanguageBindingTest *)new Test_Impl() ); + Reference< XInvocation > xInvok( new XLB_Invocation( xMgr, xOriginal ) ); + Reference< XLanguageBindingTest > xLBT( xAdapFac->createAdapter( + xInvok, ::getCppuType( (const Reference< XLanguageBindingTest > *)0 ) ), UNO_QUERY ); + Reference< XLanguageBindingTest > xLBT2( + xAdapFac->createAdapter( + xInvok, ::getCppuType( (const Reference< XLanguageBindingTest > *)0 ) ), UNO_QUERY ); + if (xLBT != xLBT2) + return sal_False; + Reference< XInterface > xLBT3( + xAdapFac->createAdapter( + xInvok, ::getCppuType( (const Reference< XInterface > *)0 ) ), UNO_QUERY ); + if (xLBT != xLBT3) + return sal_False; + Type ar[ 2 ] = { + ::getCppuType( (const Reference< XLBTestBase > *)0 ), + ::getCppuType( (const Reference< XInterface > *)0 ) }; + Reference< XInterface > xLBT4( + xAdapFac2->createAdapter( xInvok, Sequence< Type >( ar, 2 ) ), UNO_QUERY ); + if (xLBT != xLBT4) + return sal_False; + Reference< XSimpleRegistry > xInvalidAdapter( + xAdapFac->createAdapter( + xInvok, ::getCppuType( (const Reference< XSimpleRegistry > *)0 ) ), UNO_QUERY ); + if (xLBT == xInvalidAdapter) + return sal_False; + + try + { + xInvalidAdapter->isValid(); + return sal_False; + } + catch (RuntimeException &) + { + } + + return (performTest( xLBT ) && raiseException( xLBT )); +} +//================================================================================================== +static sal_Bool test_invocation( const Reference< XMultiServiceFactory > & xMgr ) +{ + Reference< XInvocationAdapterFactory > xAdapFac( + xMgr->createInstance( OUString::createFromAscii("com.sun.star.script.InvocationAdapterFactory") ), UNO_QUERY ); + Reference< XSingleServiceFactory > xInvocFac( + xMgr->createInstance( OUString::createFromAscii("com.sun.star.script.Invocation") ), UNO_QUERY ); + + Reference< XLanguageBindingTest > xOriginal( (XLanguageBindingTest *)new Test_Impl() ); + Any aOriginal( &xOriginal, ::getCppuType( &xOriginal ) ); + Reference< XInvocation > xInvok( + xInvocFac->createInstanceWithArguments( Sequence< Any >( &aOriginal, 1 ) ), UNO_REF_QUERY ); + + Reference< XLanguageBindingTest > xLBT( xAdapFac->createAdapter( + xInvok, ::getCppuType( (const Reference< XLanguageBindingTest > *)0 ) ), UNO_QUERY ); + + return (performTest( xLBT ) && raiseException( xLBT )); +} + +SAL_IMPLEMENT_MAIN() +{ + Reference< XMultiServiceFactory > xMgr( createRegistryServiceFactory( + OUString( RTL_CONSTASCII_USTRINGPARAM("stoctest.rdb") ) ) ); + + try + { + Reference< XImplementationRegistration > xImplReg( + xMgr->createInstance( + OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.ImplementationRegistration") ) ), + UNO_QUERY ); + OSL_ENSURE( xImplReg.is(), "### no impl reg!" ); + + xImplReg->registerImplementation( + OUString::createFromAscii("com.sun.star.loader.SharedLibrary"), + OUString::createFromAscii("invocadapt.uno" SAL_DLLEXTENSION), + Reference< XSimpleRegistry >() ); + xImplReg->registerImplementation( + OUString::createFromAscii("com.sun.star.loader.SharedLibrary"), + OUString::createFromAscii("stocservices.uno" SAL_DLLEXTENSION), + Reference< XSimpleRegistry >() ); + xImplReg->registerImplementation( + OUString::createFromAscii("com.sun.star.loader.SharedLibrary"), + OUString::createFromAscii("invocation.uno" SAL_DLLEXTENSION), + Reference< XSimpleRegistry >() ); + xImplReg->registerImplementation( + OUString::createFromAscii("com.sun.star.loader.SharedLibrary"), + OUString::createFromAscii("reflection.uno" SAL_DLLEXTENSION), + Reference< XSimpleRegistry >() ); + xImplReg->registerImplementation( + OUString::createFromAscii("com.sun.star.loader.SharedLibrary"), + OUString::createFromAscii("introspection.uno" SAL_DLLEXTENSION), + Reference< XSimpleRegistry >() ); + + if (test_adapter( xMgr )) + { + fprintf( stderr, "> test_iadapter() succeeded.\n" ); + if (test_invocation( xMgr )) + { + fprintf( stderr, "> test_invocation() succeeded.\n" ); + } + } + } + catch (Exception & rExc) + { + fprintf( stderr, "> exception occured: " ); + OString aMsg( OUStringToOString( rExc.Message, RTL_TEXTENCODING_ASCII_US ) ); + fprintf( stderr, "%s\n", aMsg.getStr() ); + } + + Reference< XComponent >( xMgr, UNO_QUERY )->dispose(); + + return 0; +} diff --git a/stoc/test/testintrosp.cxx b/stoc/test/testintrosp.cxx new file mode 100644 index 000000000000..a706f8666fee --- /dev/null +++ b/stoc/test/testintrosp.cxx @@ -0,0 +1,1617 @@ +/************************************************************************* + * + * 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/main.h> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase4.hxx> +#include <cppuhelper/servicefactory.hxx> +#include <osl/diagnose.h> + +//#include <vos/dynload.hxx> + +#include <ModuleA/XIntroTest.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/XIntrospection.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/beans/XExactName.hpp> +#include <com/sun/star/container/XElementAccess.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/reflection/XIdlReflection.hpp> +//#include <com/sun/star/registry/XSimpleRegistry.hpp> +#include <com/sun/star/registry/XImplementationRegistration.hpp> +#include <com/sun/star/lang/XComponent.hpp> + +#include <stdio.h> +#include <string.h> + + +using namespace rtl; +using namespace cppu; +//using namespace vos; +using namespace ModuleA; +//using namespace ModuleB; +//using namespace ModuleC; +//using namespace ModuleA::ModuleB; +using namespace com::sun::star::uno; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace com::sun::star::registry; +using namespace com::sun::star::reflection; +using namespace com::sun::star::container; +using namespace com::sun::star::beans::PropertyAttribute; + + +typedef WeakImplHelper4< XIntroTest, XPropertySet, XNameAccess, XIndexAccess > ImplIntroTestHelper; +typedef WeakImplHelper1< XPropertySetInfo > ImplPropertySetInfoHelper; + + +#define DEFAULT_INDEX_ACCESS_COUNT 10 +#define DEFAULT_NAME_ACCESS_COUNT 5 + +#if OSL_DEBUG_LEVEL > 0 +#define TEST_ENSHURE(c, m) OSL_ENSURE(c, m) +#else +#define TEST_ENSHURE(c, m) OSL_VERIFY(c) +#endif + +//class IntroTestWritelnOutput; + + + +//************************************************************** +//*** Hilfs-Funktion, um vom Type eine XIdlClass zu bekommen *** +//************************************************************** +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::createFromAscii("com.sun.star.reflection.CoreReflection") ), UNO_QUERY ); + OSL_ENSURE( xRefl.is(), "### no corereflection!" ); + } + xRetClass = xRefl->forName( sOWName ); + } + return xRetClass; +} + + +//**************************************************** +//*** Hilfs-Funktion, um Any als UString auszugeben *** +//**************************************************** +// ACHTUNG: Kann mal an eine zentrale Stelle uebernommen werden +// Wird zunaechst nur fuer einfache Datentypen ausgefuehrt + +OUString AnyToString( const Any& aValue, sal_Bool bIncludeType, const Reference< XMultiServiceFactory > & xMgr ) +{ + Type aValType = aValue.getValueType(); + TypeClass eType = aValType.getTypeClass(); + char pBuffer[50]; + + OUString aRetStr; + switch( eType ) + { + case TypeClass_TYPE: aRetStr = OUString::createFromAscii("TYPE TYPE"); break; + case TypeClass_INTERFACE: aRetStr = OUString::createFromAscii("TYPE INTERFACE"); break; + case TypeClass_SERVICE: aRetStr = OUString::createFromAscii("TYPE SERVICE"); break; + case TypeClass_STRUCT: aRetStr = OUString::createFromAscii("TYPE STRUCT"); break; + case TypeClass_TYPEDEF: aRetStr = OUString::createFromAscii("TYPE TYPEDEF"); break; + case TypeClass_UNION: aRetStr = OUString::createFromAscii("TYPE UNION"); break; + case TypeClass_ENUM: aRetStr = OUString::createFromAscii("TYPE ENUM"); break; + case TypeClass_EXCEPTION: aRetStr = OUString::createFromAscii("TYPE EXCEPTION"); break; + case TypeClass_ARRAY: aRetStr = OUString::createFromAscii("TYPE ARRAY"); break; + case TypeClass_SEQUENCE: aRetStr = OUString::createFromAscii("TYPE SEQUENCE"); break; + case TypeClass_VOID: aRetStr = OUString::createFromAscii("TYPE void"); break; + case TypeClass_ANY: aRetStr = OUString::createFromAscii("TYPE any"); break; + case TypeClass_UNKNOWN: aRetStr = OUString::createFromAscii("TYPE unknown"); break; + case TypeClass_BOOLEAN: + { + sal_Bool b = *(sal_Bool*)aValue.getValue(); + //aRet.setValue( &b, getCppuBooleanType() ); + //aValue >>= b; + aRetStr = OUString::valueOf( b ); + break; + } + case TypeClass_CHAR: + { + sal_Unicode c = *(sal_Unicode*)aValue.getValue(); + //aValue >>= c; + //getCppuCharType() + aRetStr = OUString::valueOf( c ); + break; + } + case TypeClass_STRING: + { + aValue >>= aRetStr; + break; + } + case TypeClass_FLOAT: + { + float f(0.0); + aValue >>= f; + snprintf( pBuffer, sizeof( pBuffer ), "%f", f ); + aRetStr = OUString( pBuffer, strlen( pBuffer ), RTL_TEXTENCODING_ASCII_US ); + break; + } + case TypeClass_DOUBLE: + { + double d(0.0); + aValue >>= d; + snprintf( pBuffer, sizeof( pBuffer ), "%f", d ); + aRetStr = OUString( pBuffer, strlen( pBuffer ), RTL_TEXTENCODING_ASCII_US ); + break; + } + case TypeClass_BYTE: + { + sal_Int8 n(0); + aValue >>= n; + aRetStr = OUString::valueOf( (sal_Int32) n ); + break; + } + case TypeClass_SHORT: + { + sal_Int16 n(0); + aValue >>= n; + aRetStr = OUString::valueOf( (sal_Int32) n ); + break; + } + case TypeClass_LONG: + { + sal_Int32 n(0); + aValue >>= n; + aRetStr = OUString::valueOf( n ); + break; + } + /* + case TypeClass_HYPER: + { + aRetStr = L"TYPE HYPER"; + break; + } + case TypeClass_UNSIGNED_SHORT: + { + aRetStr = StringToUString(WSString(aValue.getUINT16()), CHARSET_SYSTEM); + break; + } + case TypeClass_UNSIGNED_LONG: + { + aRetStr = StringToUString(WSString(aValue.getUINT32()), CHARSET_SYSTEM); + break; + } + case TypeClass_UNSIGNED_HYPER: + { + aRetStr = L"TYPE UNSIGNED_HYPER"; + break; + } + */ + default: ; + } + + if( bIncludeType ) + { + Reference< XIdlClass > xIdlClass = TypeToIdlClass( aValType, xMgr ); + aRetStr = aRetStr + OUString( OUString::createFromAscii(" (Typ: ") ) + xIdlClass->getName() + OUString::createFromAscii(")"); + } + return aRetStr; +} + +/* +// Hilfs-Funktion, um ein UString in einen Any zu konvertieren +UsrAny StringToAny( UString aStr, TypeClass eTargetType ) +{ + UsrAny aRetAny; + switch( eTargetType ) + { + case TypeClass_INTERFACE: break; + case TypeClass_SERVICE: break; + case TypeClass_STRUCT: break; + case TypeClass_TYPEDEF: break; + case TypeClass_UNION: break; + case TypeClass_ENUM: break; + case TypeClass_EXCEPTION: break; + case TypeClass_ARRAY: break; + case TypeClass_SEQUENCE: break; + case TypeClass_VOID: break; + case TypeClass_ANY: break; + case TypeClass_UNKNOWN: break; + case TypeClass_BOOLEAN: aRetAny.setBOOL( short(aStr)!=0 ); break; + case TypeClass_CHAR: aRetAny.setChar( char(aStr) ); break; + case TypeClass_STRING: aRetAny.setString( aStr ); break; + case TypeClass_FLOAT: aRetAny.setFloat( (float)strtod( aStr.GetStr(), NULL ) ); break; + case TypeClass_DOUBLE: aRetAny.setDouble( strtod( aStr.GetStr(), NULL ) ); break; + case TypeClass_BYTE: aRetAny.setBYTE( BYTE(short(aStr)) ); break; + case TypeClass_SHORT: aRetAny.setINT16( short(aStr) ); break; + case TypeClass_LONG: aRetAny.setINT32( long(aStr) ); break; + case TypeClass_HYPER: break; + case TypeClass_UNSIGNED_SHORT: aRetAny.setUINT16( USHORT(aStr) ); break; + case TypeClass_UNSIGNED_LONG: aRetAny.setUINT32( ULONG(aStr) ); break; + case TypeClass_UNSIGNED_HYPER: break; + } + return aRetAny; +} +*/ + + +//***************************************** +//*** XPropertySetInfo fuer Test-Klasse *** +//***************************************** + +class ImplPropertySetInfo : public ImplPropertySetInfoHelper +{ + friend class ImplIntroTest; + + Reference< XMultiServiceFactory > mxMgr; + +public: + ImplPropertySetInfo( const Reference< XMultiServiceFactory > & xMgr ) + : mxMgr( xMgr ) {} + //: mxMgr( xMgr ), ImplPropertySetInfoHelper( xMgr ) {} + +/* + // Methoden von XInterface + virtual sal_Bool SAL_CALL queryInterface( const Uik & rUik, Any & ifc ) throw( RuntimeException ); + virtual void SAL_CALL acquire() throw() { OWeakObject::acquire(); } + virtual void SAL_CALL release() throw() { OWeakObject::release(); } + //ALT: sal_Bool queryInterface( Uik aUik, Reference<XInterface> & rOut ); +*/ + + // Methods of XPropertySetInfo + virtual Sequence< Property > SAL_CALL getProperties( ) + throw(RuntimeException); + virtual Property SAL_CALL getPropertyByName( const OUString& aName ) + throw(UnknownPropertyException, RuntimeException); + virtual sal_Bool SAL_CALL hasPropertyByName( const OUString& Name ) + throw(RuntimeException); + //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 XInterface +sal_Bool SAL_CALL ImplPropertySetInfo::queryInterface( const Uik & rUik, Any & ifc ) + throw( RuntimeException ) +{ + // PropertySet-Implementation + if( com::sun::star::uno::queryInterface( rUik, ifc, + SAL_STATIC_CAST(XPropertySetInfo*, this) ) ) + return sal_True; + + return OWeakObject::queryInterface( rUik, ifc ); +} + +sal_Bool ImplPropertySetInfo::queryInterface( Uik aUik, Reference<XInterface> & rOut ) +{ + if( aUik == XPropertySetInfo::getSmartUik() ) + rOut = (XPropertySetInfo *)this; + else + UsrObject::queryInterface( aUik, rOut ); + return rOut.is(); +} +*/ + +Sequence< Property > ImplPropertySetInfo::getProperties(void) + throw( RuntimeException ) +{ + static Sequence<Property> * pSeq = NULL; + + if( !pSeq ) + { + // die Informationen für die Properties "Width", "Height" und "Name" anlegen + pSeq = new Sequence<Property>( 3 ); + Property * pAry = pSeq->getArray(); + + pAry[0].Name = OUString::createFromAscii("Factor"); + pAry[0].Handle = -1; + pAry[0].Type = getCppuType( (double*) NULL ); + //pAry[0].Type = TypeToIdlClass( getCppuType( (double*) NULL ), mxMgr ); + //pAry[0].Type = Double_getReflection()->getIdlClass(); + pAry[0].Attributes = BOUND | TRANSIENT; + + pAry[1].Name = OUString::createFromAscii("MyCount"); + pAry[1].Handle = -1; + pAry[1].Type = getCppuType( (sal_Int32*) NULL ); + //pAry[1].Type = TypeToIdlClass( getCppuType( (sal_Int32*) NULL ), mxMgr ); + //pAry[1].Type = INT32_getReflection()->getIdlClass(); + pAry[1].Attributes = BOUND | TRANSIENT; + + pAry[2].Name = OUString::createFromAscii("Info"); + pAry[2].Handle = -1; + pAry[2].Type = getCppuType( (OUString*) NULL ); + //pAry[2].Type = TypeToIdlClass( getCppuType( (OUString*) NULL ), mxMgr ); + //pAry[2].Type = OUString_getReflection()->getIdlClass(); + pAry[2].Attributes = TRANSIENT; + } + // Die Information über alle drei Properties liefern. + return *pSeq; +} + +Property ImplPropertySetInfo::getPropertyByName(const OUString& Name) + throw( UnknownPropertyException, RuntimeException ) +{ + Sequence<Property> aSeq = getProperties(); + const Property * pAry = aSeq.getConstArray(); + + for( sal_Int32 i = aSeq.getLength(); i--; ) + { + if( pAry[i].Name == Name ) + return pAry[i]; + } + // Property unbekannt, also leere liefern + return Property(); +} + +sal_Bool ImplPropertySetInfo::hasPropertyByName(const OUString& Name) + throw( RuntimeException ) +{ + Sequence<Property> aSeq = getProperties(); + const Property * pAry = aSeq.getConstArray(); + + for( sal_Int32 i = aSeq.getLength(); i--; ) + { + if( pAry[i].Name == Name ) + return sal_True; + } + // Property unbekannt, also leere liefern + return sal_False; +} + + + + +//***************************************************************** + + + +class ImplIntroTest : public ImplIntroTestHelper +{ + Reference< XMultiServiceFactory > mxMgr; + + friend class ImplPropertySetInfo; + + // Properties fuer das PropertySet + Any aAnyArray[10]; + + // Optionale Schnittstelle fuer die writeln-Ausgabe + //IntroTestWritelnOutput* m_pOutput; + + Reference< XPropertySetInfo > m_xMyInfo; + + OUString m_ObjectName; + + sal_Int16 m_nMarkusAge; + sal_Int16 m_nMarkusChildrenCount; + + long m_lDroenk; + sal_Int16 m_nBla; + sal_Int16 m_nBlub; + sal_Int16 m_nGulp; + sal_Int16 m_nLaber; + TypeClass eTypeClass; + Sequence< OUString > aStringSeq; + Sequence< Sequence< Sequence< sal_Int16 > > > aMultSeq; + Reference< XIntroTest > m_xIntroTest; + + // Daten fuer NameAccess + Reference< XIntroTest >* pNameAccessTab; + + // Daten fuer IndexAccess + Reference< XIntroTest >* pIndexAccessTab; + sal_Int16 iIndexAccessCount; + + // struct-Properties + Property m_aFirstStruct; + PropertyValue m_aSecondStruct; + + // Listener merken (zunaechst einfach, nur einen pro Property) + Reference< XPropertyChangeListener > aPropChangeListener; + OUString aPropChangeListenerStr; + Reference< XVetoableChangeListener > aVetoPropChangeListener; + OUString aVetoPropChangeListenerStr; + + void Init( void ); + +public: + ImplIntroTest( const Reference< XMultiServiceFactory > & xMgr ) + : mxMgr( xMgr ) + //: mxMgr( xMgr ), ImplIntroTestHelper( xMgr ) + { + Init(); + } + + /* + ImplIntroTest( IntroTestWritelnOutput* pOutput_ ) + { + Init(); + m_pOutput = pOutput_; + } + */ + + //SMART_UNO_DECLARATION(ImplIntroTest,UsrObject); + + //BOOL queryInterface( Uik aUik, Reference< XInterface > & rOut ); + //Reference< XIdlClass > getIdlClass(); + + // Trotz virtual inline, um Schreibarbeit zu sparen (nur fuer Testzwecke) + // 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& PropertyName ) + throw(UnknownPropertyException, WrappedTargetException, RuntimeException); + virtual void SAL_CALL addPropertyChangeListener( const OUString& /*aPropertyName*/, const Reference< XPropertyChangeListener >& /*xListener*/ ) + 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& /*PropertyName*/, const Reference< XVetoableChangeListener >& /*aListener*/ ) + throw(UnknownPropertyException, WrappedTargetException, RuntimeException) + {} + virtual void SAL_CALL removeVetoableChangeListener( const OUString& /*PropertyName*/, const Reference< XVetoableChangeListener >& /*aListener*/ ) + throw(UnknownPropertyException, WrappedTargetException, RuntimeException) + {} + + /* + virtual void setIndexedPropertyValue(const OUString& aPropertyName, INT32 nIndex, const Any& aValue) {} + virtual Any getIndexedPropertyValue(const UString& aPropertyName, INT32 nIndex) const { return Any(); } + virtual void addPropertyChangeListener(const UString& aPropertyName, const XPropertyChangeListenerRef& aListener) + THROWS( (UnknownPropertyException, WrappedTargetException, UsrSystemException) ) {} + virtual void removePropertyChangeListener(const UString& aPropertyName, const XPropertyChangeListenerRef& aListener) + THROWS( (UnknownPropertyException, WrappedTargetException, UsrSystemException) ) {} + virtual void addVetoableChangeListener(const UString& aPropertyName, const XVetoableChangeListenerRef& aListener) + THROWS( (UnknownPropertyException, WrappedTargetException, UsrSystemException) ) {} + virtual void removeVetoableChangeListener(const UString& aPropertyName, const XVetoableChangeListenerRef& aListener) + THROWS( (UnknownPropertyException, WrappedTargetException, UsrSystemException) ) {} + */ + + // XIntroTest-Methoden + // Attributes + virtual OUString SAL_CALL getObjectName() throw(RuntimeException) + { return m_ObjectName; } + virtual void SAL_CALL setObjectName( const OUString& _objectname ) throw(RuntimeException) + { m_ObjectName = _objectname; } + virtual OUString SAL_CALL getFirstName() + throw(RuntimeException); + virtual OUString SAL_CALL getLastName() throw(RuntimeException) + { return OUString( OUString::createFromAscii("Meyer") ); } + virtual sal_Int16 SAL_CALL getAge() throw(RuntimeException) + { return m_nMarkusAge; } + virtual sal_Int16 SAL_CALL getChildrenCount() throw(RuntimeException) + { return m_nMarkusChildrenCount; } + virtual void SAL_CALL setChildrenCount( sal_Int16 _childrencount ) throw(RuntimeException) + { m_nMarkusChildrenCount = _childrencount; } + virtual Property SAL_CALL getFirstStruct() throw(RuntimeException) + { return m_aFirstStruct; } + virtual void SAL_CALL setFirstStruct( const Property& _firststruct ) throw(RuntimeException) + { m_aFirstStruct = _firststruct; } + virtual PropertyValue SAL_CALL getSecondStruct() throw(RuntimeException) + { return m_aSecondStruct; } + virtual void SAL_CALL setSecondStruct( const PropertyValue& _secondstruct ) throw(RuntimeException) + { m_aSecondStruct = _secondstruct; } + + // Methods + virtual void SAL_CALL writeln( const OUString& Text ) + throw(RuntimeException); + virtual sal_Int32 SAL_CALL getDroenk( ) throw(RuntimeException) + { return m_lDroenk; } + virtual Reference< ::ModuleA::XIntroTest > SAL_CALL getIntroTest( ) throw(RuntimeException); + virtual sal_Int32 SAL_CALL getUps( sal_Int32 l ) throw(RuntimeException) + { return 2*l; } + virtual void SAL_CALL setDroenk( sal_Int32 l ) throw(RuntimeException) + { m_lDroenk = l; } + virtual sal_Int16 SAL_CALL getBla( ) throw(RuntimeException) + { return m_nBla; } + virtual void SAL_CALL setBla( sal_Int32 n ) throw(RuntimeException) + { m_nBla = (sal_Int16)n; } + virtual sal_Int16 SAL_CALL getBlub( ) throw(RuntimeException) + { return m_nBlub; } + virtual void SAL_CALL setBlub( sal_Int16 n ) throw(RuntimeException) + { m_nBlub = n; } + virtual sal_Int16 SAL_CALL getGulp( ) throw(RuntimeException) + { return m_nGulp; } + virtual sal_Int16 SAL_CALL setGulp( sal_Int16 n ) throw(RuntimeException) + { m_nGulp = n; return 1; } + virtual TypeClass SAL_CALL getTypeClass( sal_Int16 /*n*/ ) throw(RuntimeException) + { return eTypeClass; } + virtual void SAL_CALL setTypeClass( TypeClass t, double /*d1*/, double /*d2*/ ) throw(RuntimeException) + { eTypeClass = t; } + virtual Sequence< OUString > SAL_CALL getStrings( ) throw(RuntimeException) + { return aStringSeq; } + virtual void SAL_CALL setStrings( const Sequence< OUString >& Strings ) throw(RuntimeException) + { aStringSeq = Strings; } + virtual void SAL_CALL setStringsPerMethod( const Sequence< OUString >& Strings, sal_Int16 /*n*/ ) throw(RuntimeException) + { aStringSeq = Strings; } + virtual Sequence< Sequence< Sequence< sal_Int16 > > > SAL_CALL getMultiSequence( ) throw(RuntimeException) + { return aMultSeq; } + virtual void SAL_CALL setMultiSequence( const Sequence< Sequence< Sequence< sal_Int16 > > >& Seq ) throw(RuntimeException) + { aMultSeq = Seq; } + virtual void SAL_CALL addPropertiesChangeListener( const Sequence< OUString >& PropertyNames, const Reference< XPropertiesChangeListener >& Listener ) + throw(RuntimeException); + virtual void SAL_CALL removePropertiesChangeListener( const Reference< XPropertiesChangeListener >& Listener ) + throw(RuntimeException); + + + // Methods of XElementAccess + virtual Type SAL_CALL getElementType( ) + throw(RuntimeException); + virtual sal_Bool SAL_CALL hasElements( ) + throw(RuntimeException); + //virtual XIdlClassRef getElementType(void) constTHROWS( (UsrSystemException) ); + //virtual BOOL hasElements(void) const THROWS( (UsrSystemException) ); + + // XNameAccess-Methoden + // Methods + virtual Any SAL_CALL getByName( const OUString& aName ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException); + virtual Sequence< OUString > SAL_CALL getElementNames( ) + throw(RuntimeException); + virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) + throw(RuntimeException); + //virtual Any getByName(const UString& Name) const + //THROWS( (NoSuchElementException, WrappedTargetException, UsrSystemException) ); + //virtual Sequence<UString> getElementNames(void) const THROWS( (UsrSystemException) ); + //virtual BOOL hasByName(const UString& Name) const THROWS( (UsrSystemException) ); + + // XIndexAccess-Methoden + // Methods + virtual sal_Int32 SAL_CALL getCount( ) + throw(RuntimeException); + virtual Any SAL_CALL getByIndex( sal_Int32 Index ) + throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException); + //virtual INT32 getCount(void) const THROWS( (UsrSystemException) ); + //virtual Any getByIndex(INT32 Index) const + //THROWS( (IndexOutOfBoundsException, WrappedTargetException, UsrSystemException) ); +}; + +//SMART_UNO_IMPLEMENTATION(ImplIntroTest,UsrObject) + +void ImplIntroTest::Init( void ) +{ + // Eindeutigen Namen verpassen + static sal_Int32 nObjCount = 0; + OUString aName( OUString::createFromAscii("IntroTest-Obj Nr. ") ); + aName += OUString::valueOf( nObjCount ); + setObjectName( aName ); + + // Properties initialisieren + aAnyArray[0] <<= 3.14; + aAnyArray[1] <<= (sal_Int32)42; + aAnyArray[2] <<= OUString( OUString::createFromAscii("Hallo") ); + + // Output-Interface + //m_pOutput = NULL; + + // Einmal fuer den internen Gebrauch die PropertySetInfo abholen + m_xMyInfo = getPropertySetInfo(); + m_xMyInfo->acquire(); // sonst raucht es am Programm-Ende ab + + m_nMarkusAge = 33; + m_nMarkusChildrenCount = 2; + + m_lDroenk = 314; + m_nBla = 42; + m_nBlub = 111; + m_nGulp = 99; + m_nLaber = 1; + eTypeClass = TypeClass_INTERFACE; + + // String-Sequence intitialisieren + aStringSeq.realloc( 3 ); + OUString* pStr = aStringSeq.getArray(); + pStr[ 0 ] = OUString( OUString::createFromAscii("String 0") ); + pStr[ 1 ] = OUString( OUString::createFromAscii("String 1") ); + pStr[ 2 ] = OUString( OUString::createFromAscii("String 2") ); + + // structs initialisieren + m_aFirstStruct.Name = OUString::createFromAscii("FirstStruct-Name"); + m_aFirstStruct.Handle = 77777; + //XIdlClassRef Type; + m_aFirstStruct.Attributes = -222; + + //XInterfaceRef Source; + Any Value; + Value <<= 2.718281828459; + m_aSecondStruct.Value = Value; + //XIdlClassRef ListenerType; + m_aSecondStruct.State = PropertyState_DIRECT_VALUE; + + // IndexAccess + iIndexAccessCount = DEFAULT_INDEX_ACCESS_COUNT; + pIndexAccessTab = NULL; + pNameAccessTab = NULL; +} + +/* +BOOL ImplIntroTest::queryInterface( Uik aUik, XInterfaceRef & rOut ) +{ + if( aUik == XIntroTest::getSmartUik() ) + rOut = (XIntroTest*)this; + else if( aUik == XPropertySet::getSmartUik() ) + rOut = (XPropertySet*)this; + else if( aUik == XNameAccess::getSmartUik() ) + rOut = (XNameAccess*)this; + else if( aUik == XIndexAccess::getSmartUik() ) + rOut = (XIndexAccess*)this; + else if( aUik == ((XElementAccess*)NULL)->getSmartUik() ) + rOut = (XElementAccess*)(XIndexAccess *)this; + else + UsrObject::queryInterface( aUik, rOut ); + return rOut.is(); +} + +XIdlClassRef ImplIntroTest::getIdlClass() +{ + static XIdlClassRef xClass = createStandardClass( L"ImplIntroTest", + UsrObject::getUsrObjectIdlClass(), 4, + XIntroTest_getReflection(), + XPropertySet_getReflection(), + XNameAccess_getReflection(), + XIndexAccess_getReflection() ); + return xClass; +} +*/ + +Reference< XPropertySetInfo > ImplIntroTest::getPropertySetInfo() + throw(RuntimeException) +{ + static ImplPropertySetInfo aInfo( mxMgr ); + // Alle Objekt haben die gleichen Properties, deshalb kann + // die Info für alle gleich sein + return &aInfo; + + //if( m_xMyInfo == NULL ) + // ((ImplIntroTest*)this)->m_xMyInfo = new ImplPropertySetInfo( this ); + //return m_xMyInfo; +} + +void ImplIntroTest::setPropertyValue( const OUString& aPropertyName, const Any& aValue ) + throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) +//void ImplIntroTest::setPropertyValue( const UString& aPropertyName, const Any& aValue ) +// THROWS( (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, UsrSystemException) ) +{ + if( aPropChangeListener.is() && aPropertyName == aPropChangeListenerStr ) + { + PropertyChangeEvent aEvt; + aEvt.Source = (OWeakObject*)this; + aEvt.PropertyName = aPropertyName; + aEvt.PropertyHandle = 0L; + //aEvt.OldValue; + //aEvt.NewValue; + //aEvt.PropagationId; + aPropChangeListener->propertyChange( aEvt ); + } + if( aVetoPropChangeListener.is() && aPropertyName == aVetoPropChangeListenerStr ) + { + PropertyChangeEvent aEvt; + aEvt.Source = (OWeakObject*)this; + aEvt.PropertyName = aVetoPropChangeListenerStr; + aEvt.PropertyHandle = 0L; + //aEvt.OldValue; + //aEvt.NewValue; + //aEvt.PropagationId; + aVetoPropChangeListener->vetoableChange( aEvt ); + } + + Sequence<Property> aPropSeq = m_xMyInfo->getProperties(); + sal_Int32 nLen = aPropSeq.getLength(); + for( sal_Int32 i = 0 ; i < nLen ; i++ ) + { + Property aProp = aPropSeq.getArray()[ i ]; + if( aProp.Name == aPropertyName ) + aAnyArray[i] = aValue; + } +} + +Any ImplIntroTest::getPropertyValue( const OUString& PropertyName ) + throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +//Any ImplIntroTest::getPropertyValue(const UString& aPropertyName) const + //THROWS( (UnknownPropertyException, WrappedTargetException, UsrSystemException) ) +{ + Sequence<Property> aPropSeq = m_xMyInfo->getProperties(); + sal_Int32 nLen = aPropSeq.getLength(); + for( sal_Int32 i = 0 ; i < nLen ; i++ ) + { + Property aProp = aPropSeq.getArray()[ i ]; + if( aProp.Name == PropertyName ) + return aAnyArray[i]; + } + return Any(); +} + +OUString ImplIntroTest::getFirstName(void) + throw(RuntimeException) +{ + return OUString( OUString::createFromAscii("Markus") ); +} + +void ImplIntroTest::writeln( const OUString& Text ) + throw(RuntimeException) +{ + OString aStr( Text.getStr(), Text.getLength(), RTL_TEXTENCODING_ASCII_US ); + + // Haben wir ein Output? + //if( m_pOutput ) + //{ + //m_pOutput->doWriteln( TextStr ); + //} + // Sonst einfach rausbraten + //else + { + printf( "%s", aStr.getStr() ); + } +} + +Reference< XIntroTest > ImplIntroTest::getIntroTest() + throw(RuntimeException) +//XIntroTestRef ImplIntroTest::getIntroTest(void) THROWS( (UsrSystemException) ) +{ + if( !m_xIntroTest.is() ) + m_xIntroTest = new ImplIntroTest( mxMgr ); + return m_xIntroTest; +} + +// Methoden von XElementAccess +Type ImplIntroTest::getElementType( ) + throw(RuntimeException) +//XIdlClassRef ImplIntroTest::getElementType(void) const THROWS( (UsrSystemException) ) +{ + // TODO + Type aRetType; + return aRetType; + //return Reference< XIdlClass >(); + //return Void_getReflection()->getIdlClass(); +} + +sal_Bool ImplIntroTest::hasElements( ) + throw(RuntimeException) +//BOOL ImplIntroTest::hasElements(void) const THROWS( (UsrSystemException) ) +{ + return sal_True; +} + +// XNameAccess-Methoden +sal_Int32 getIndexForName( const OUString& ItemName ) +{ + OUString aLeftStr = ItemName.copy( 0, 4 ); + if( aLeftStr == OUString::createFromAscii("Item") ) + { + // TODO + OUString aNumStr = ItemName.copy( 4 ); + //sal_Int32 iIndex = (INT32)UStringToString( aNumStr, CHARSET_SYSTEM ); + //if( iIndex < DEFAULT_NAME_ACCESS_COUNT ) + //return iIndex; + } + return -1; +} + + +Any ImplIntroTest::getByName( const OUString& aName ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException) +//Any ImplIntroTest::getByName(const UString& Name) const + //THROWS( (NoSuchElementException, WrappedTargetException, UsrSystemException) ) +{ + Any aRetAny; + + if( !pNameAccessTab ) + ((ImplIntroTest*)this)->pNameAccessTab = new Reference< XIntroTest >[ DEFAULT_NAME_ACCESS_COUNT ]; + + sal_Int32 iIndex = getIndexForName( aName ); + if( iIndex != -1 ) + { + if( !pNameAccessTab[iIndex].is() ) + { + ImplIntroTest* p = new ImplIntroTest( mxMgr ); + OUString aName2( OUString::createFromAscii("IntroTest by Name-Access, Index = ") ); + aName2 += OUString::valueOf( iIndex ); + //aName2 = aName2 + StringToUString( String( iIndex ), CHARSET_SYSTEM ); + p->setObjectName( aName2 ); + pNameAccessTab[iIndex] = p; + } + + Reference< XIntroTest > xRet = pNameAccessTab[iIndex]; + aRetAny = makeAny( xRet ); + + //aRetAny.set( &xRet, XIntroTest_getReflection() ); + //return (UsrObject*)(XIntroTest*)pNameAccessTab[iIndex]; + } + return aRetAny; +} + +Sequence< OUString > ImplIntroTest::getElementNames( ) + throw(RuntimeException) +//Sequence<UString> ImplIntroTest::getElementNames(void) const THROWS( (UsrSystemException) ) +{ + Sequence<OUString> aStrSeq( DEFAULT_NAME_ACCESS_COUNT ); + OUString* pStr = aStrSeq.getArray(); + for( sal_Int32 i = 0 ; i < DEFAULT_NAME_ACCESS_COUNT ; i++ ) + { + OUString aName( OUString::createFromAscii("Item") ); + aName += OUString::valueOf( i ); + //aName = aName + StringToUString( i, CHARSET_SYSTEM ); + pStr[i] = aName; + } + return aStrSeq; +} + +sal_Bool ImplIntroTest::hasByName( const OUString& aName ) + throw(RuntimeException) +//BOOL ImplIntroTest::hasByName(const UString& Name) const THROWS( (UsrSystemException) ) +{ + return ( getIndexForName( aName ) != -1 ); +} + +// XIndexAccess-Methoden +sal_Int32 ImplIntroTest::getCount( ) + throw(RuntimeException) +//sal_Int32 ImplIntroTest::getCount(void) const THROWS( (UsrSystemException) ) +{ + return iIndexAccessCount; +} + +Any ImplIntroTest::getByIndex( sal_Int32 Index ) + throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException) +//Any ImplIntroTest::getByIndex( sal_Int32 Index ) const + //THROWS( (IndexOutOfBoundsException, WrappedTargetException, UsrSystemException) ) +{ + Any aRetAny; + + if( !pIndexAccessTab ) + ((ImplIntroTest*)this)->pIndexAccessTab = new Reference< XIntroTest >[ iIndexAccessCount ]; + + if( Index < iIndexAccessCount ) + { + if( !pNameAccessTab[Index].is() ) + { + ImplIntroTest* p = new ImplIntroTest( mxMgr ); + OUString aName( OUString::createFromAscii("IntroTest by Index-Access, Index = ") ); + aName += OUString::valueOf( Index ); + //aName = aName + StringToUString( String( iIndex ), CHARSET_SYSTEM ); + p->setObjectName( aName ); + pIndexAccessTab[Index] = p; + } + Reference< XIntroTest > xRet = pIndexAccessTab[Index]; + aRetAny = makeAny( xRet ); + } + return aRetAny; +} + +void ImplIntroTest::addPropertiesChangeListener( const Sequence< OUString >& /*PropertyNames*/, + const Reference< XPropertiesChangeListener >& /*Listener*/ ) + throw(RuntimeException) +//void ImplIntroTest::addPropertiesChangeListener +//(const Sequence< UString >& PropertyNames, const XPropertiesChangeListenerRef& Listener) + //THROWS( (UsrSystemException) ) +{ +} + +void ImplIntroTest::removePropertiesChangeListener +( const Reference< XPropertiesChangeListener >& /*Listener*/ ) + throw(RuntimeException) +//void ImplIntroTest::removePropertiesChangeListener(const XPropertiesChangeListenerRef& Listener) + //THROWS( (UsrSystemException) ) +{ +} + + + +struct DefItem +{ + char const * pName; + sal_Int32 nConcept; +}; + +// Spezial-Wert fuer Method-Concept, um "normale" Funktionen kennzeichnen zu koennen +#define MethodConcept_NORMAL_IMPL 0x80000000 + + +// Test-Objekt liefern +Any getIntrospectionTestObject( const Reference< XMultiServiceFactory > & xMgr ) +{ + Any aObjAny; + Reference< XIntroTest > xTestObj = new ImplIntroTest( xMgr ); + aObjAny.setValue( &xTestObj, ::getCppuType( (const Reference< XIntroTest > *)0 ) ); + return aObjAny; +} + +static sal_Bool test_introsp( Reference< XMultiServiceFactory > xMgr, + Reference< XIdlReflection > /*xRefl*/, Reference< XIntrospection > xIntrospection ) +{ + DefItem pPropertyDefs[] = + { + { "Factor", PropertyConcept::PROPERTYSET }, + { "MyCount", PropertyConcept::PROPERTYSET }, + { "Info", PropertyConcept::PROPERTYSET }, + { "ObjectName", PropertyConcept::ATTRIBUTES }, + { "FirstName", PropertyConcept::ATTRIBUTES }, + { "LastName", PropertyConcept::ATTRIBUTES }, + { "Age", PropertyConcept::ATTRIBUTES }, + { "ChildrenCount", PropertyConcept::ATTRIBUTES }, + { "FirstStruct", PropertyConcept::ATTRIBUTES }, + { "SecondStruct", PropertyConcept::ATTRIBUTES }, + { "Droenk", PropertyConcept::METHODS }, + { "IntroTest", PropertyConcept::METHODS }, + { "Bla", PropertyConcept::METHODS }, + { "Blub", PropertyConcept::METHODS }, + { "Gulp", PropertyConcept::METHODS }, + { "Strings", PropertyConcept::METHODS }, + { "MultiSequence", PropertyConcept::METHODS }, + { "PropertySetInfo", PropertyConcept::METHODS }, + { "ElementType", PropertyConcept::METHODS }, + { "ElementNames", PropertyConcept::METHODS }, + { "Count", PropertyConcept::METHODS }, + { "Types", PropertyConcept::METHODS }, + { "ImplementationId", PropertyConcept::METHODS }, + { NULL, 0 } + }; + + // Tabelle der Property-Namen, die gefunden werden muessen +// char* pDemandedPropNames[] = +// { +// "Factor", +// "MyCount", +// "Info", +// "ObjectName", +// "FirstName", +// "LastName", +// "Age", +// "ChildrenCount", +// "FirstStruct", +// "SecondStruct", +// "Droenk", +// "IntroTest", +// "Bla", +// "Blub", +// "Gulp", +// "Strings", +// "MultiSequence", +// "PropertySetInfo", +// "ElementType", +// "ElementNames", +// "Count", +// "Types" +// "ImplementationId" +// }; + + char const * pDemandedPropVals[] = + { + "3.140000", + "42", + "Hallo", + "IntroTest-Obj Nr. 0", + "Markus", + "Meyer", + "33", + "2", + "TYPE STRUCT", + "TYPE STRUCT", + "314", + "TYPE INTERFACE", + "42", + "111", + "99", + "TYPE SEQUENCE", + "TYPE SEQUENCE", + "TYPE INTERFACE", + "TYPE TYPE", + "TYPE SEQUENCE", + "10", + "TYPE SEQUENCE", + "TYPE SEQUENCE", + }; + + char const * pDemandedModifiedPropVals[] = + { + "4.140000", + "43", + "Hallo (Modified!)", + "IntroTest-Obj Nr. 0 (Modified!)", + "Markus", + "Meyer", + "33", + "3", + "Wert wurde nicht modifiziert", + "Wert wurde nicht modifiziert", + "315", + "Wert wurde nicht modifiziert", + "42", + "112", + "99", + "Wert wurde nicht modifiziert", + "Wert wurde nicht modifiziert", + "Wert wurde nicht modifiziert", + "Wert wurde nicht modifiziert", + "Wert wurde nicht modifiziert", + "10", + "Wert wurde nicht modifiziert" + "Wert wurde nicht modifiziert" + }; + + char const * pDemandedPropTypes[] = + { + "double", + "long", + "string", + "string", + "string", + "string", + "short", + "short", + "com.sun.star.beans.Property", + "com.sun.star.beans.PropertyValue", + "long", + "ModuleA.XIntroTest", + "short", + "short", + "short", + "[]string", + "[][][]short", + "com.sun.star.beans.XPropertySetInfo", + "type", + "[]string", + "long", + "[]type", + "[]byte", + }; + //is() nDemandedPropCount = 22; + + + DefItem pMethodDefs[] = + { + { "queryInterface", MethodConcept_NORMAL_IMPL }, + { "acquire", MethodConcept::DANGEROUS }, + { "release", MethodConcept::DANGEROUS }, + { "writeln", MethodConcept_NORMAL_IMPL }, + { "getDroenk", MethodConcept::PROPERTY }, + { "getIntroTest", MethodConcept::PROPERTY }, + { "getUps", MethodConcept_NORMAL_IMPL }, + { "setDroenk", MethodConcept::PROPERTY }, + { "getBla", MethodConcept::PROPERTY }, + { "setBla", MethodConcept_NORMAL_IMPL }, + { "getBlub", MethodConcept::PROPERTY }, + { "setBlub", MethodConcept::PROPERTY }, + { "getGulp", MethodConcept::PROPERTY }, + { "setGulp", MethodConcept_NORMAL_IMPL }, + { "getTypeClass", MethodConcept_NORMAL_IMPL }, + { "setTypeClass", MethodConcept_NORMAL_IMPL }, + { "getStrings", MethodConcept::PROPERTY }, + { "setStrings", MethodConcept::PROPERTY }, + { "setStringsPerMethod", MethodConcept_NORMAL_IMPL }, + { "getMultiSequence", MethodConcept::PROPERTY }, + { "setMultiSequence", MethodConcept::PROPERTY }, + { "addPropertiesChangeListener", MethodConcept::LISTENER }, + { "removePropertiesChangeListener", MethodConcept::LISTENER }, + { "getPropertySetInfo", MethodConcept::PROPERTY }, + { "setPropertyValue", MethodConcept_NORMAL_IMPL }, + { "getPropertyValue", MethodConcept_NORMAL_IMPL }, + { "addPropertyChangeListener", MethodConcept::LISTENER }, + { "removePropertyChangeListener", MethodConcept::LISTENER }, + { "addVetoableChangeListener", MethodConcept::LISTENER }, + { "removeVetoableChangeListener", MethodConcept::LISTENER }, + { "getElementType", MethodConcept::PROPERTY | MethodConcept::NAMECONTAINER| MethodConcept::INDEXCONTAINER | MethodConcept::ENUMERATION }, + { "hasElements", MethodConcept::NAMECONTAINER | MethodConcept::INDEXCONTAINER | MethodConcept::ENUMERATION }, + { "getByName", MethodConcept::NAMECONTAINER }, + { "getElementNames", MethodConcept::PROPERTY | MethodConcept::NAMECONTAINER }, + { "hasByName", MethodConcept::NAMECONTAINER }, + { "getCount", MethodConcept::PROPERTY | MethodConcept::INDEXCONTAINER }, + { "getByIndex", MethodConcept::INDEXCONTAINER }, + { "getTypes", MethodConcept::PROPERTY }, + { "getImplementationId", MethodConcept::PROPERTY }, + { "queryAdapter", MethodConcept_NORMAL_IMPL }, + { NULL, 0 } + }; + + OString aErrorStr; + + //****************************************************** + + // Test-Objekt anlegen + Any aObjAny = getIntrospectionTestObject( xMgr ); + + // Introspection-Service holen + //Reference< XMultiServiceFactory > xServiceManager(getProcessServiceManager(), USR_QUERY); + //Reference< XIntrospection > xIntrospection( xMgr->createInstance(L"com.sun.star.beans.Introspection"), UNO_QUERY ); + //TEST_ENSHURE( xIntrospection.is(), "Creation of introspection instance failed" ); + //if( !xIntrospection.is() ) + //return sal_False; + + // und unspecten + Reference< XIntrospectionAccess > xAccess = xIntrospection->inspect( aObjAny ); + xAccess = xIntrospection->inspect( aObjAny ); + xAccess = xIntrospection->inspect( aObjAny ); + TEST_ENSHURE( xAccess.is(), "introspection failed, no XIntrospectionAccess returned" ); + if( !xAccess.is() ) + return sal_False; + + // Ergebnis der Introspection pruefen + + // XPropertySet-UIK ermitteln + Type aType = getCppuType( (Reference< XPropertySet >*) NULL ); + //typelib_InterfaceTypeDescription* pTypeDesc = NULL; + //aType.getDescription( (typelib_TypeDescription**)&pTypeDesc ); + //Uik aPropertySetUik = *(Uik*)&pTypeDesc->aUik; + //typelib_typedescription_release( (typelib_TypeDescription*)pTypeDesc ); + + Reference< XInterface > xPropSetIface = xAccess->queryAdapter( aType ); + //Reference< XInterface > xPropSetIface = xAccess->queryAdapter( aPropertySetUik ); + Reference< XPropertySet > xPropSet( xPropSetIface, UNO_QUERY ); + //XPropertySetRef xPropSet = (XPropertySet*)xPropSetIface-> + // queryInterface( XPropertySet::getSmartUik() ); + TEST_ENSHURE( xPropSet.is(), "Could not get XPropertySet by queryAdapter()" ); + + // XExactName + Reference< XExactName > xExactName( xAccess, UNO_QUERY ); + TEST_ENSHURE( xExactName.is(), "Introspection unterstuetzt kein ExactName" ); + + // Schleife ueber alle Kombinationen von Concepts + for( sal_Int32 nConcepts = 0 ; nConcepts < 16 ; nConcepts++ ) + { +//printf( "*******************************************************\n" ); +//printf( "nConcepts = %ld\n", nConcepts ); + + // Wieviele Properties sollten es sein + sal_Int32 nDemandedPropCount = 0; + sal_Int32 iList = 0; + while( pPropertyDefs[ iList ].pName ) + { + if( pPropertyDefs[ iList ].nConcept & nConcepts ) + nDemandedPropCount++; + iList++; + } + + if( xPropSet.is() ) + { + Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo(); + //Sequence<Property> aRetSeq = xPropSetInfo->getProperties(); + Sequence<Property> aRetSeq = xAccess->getProperties( nConcepts ); + + sal_Int32 nLen = aRetSeq.getLength(); + + aErrorStr = "Expected to find "; + aErrorStr += OString::valueOf( nDemandedPropCount ); + aErrorStr += " properties but found "; + aErrorStr += OString::valueOf( nLen ); + TEST_ENSHURE( nLen == nDemandedPropCount, aErrorStr.getStr() ); + + // cout << "**********************************\n"; + // cout << "*** Ergebnis der Introspection ***\n"; + // cout << "**********************************\n"; + // cout << "\nIntrospection hat " << nLen << " Properties gefunden:\n"; + + const Property* pProps = aRetSeq.getConstArray(); + Any aPropVal; + sal_Int32 i; + iList = 0; + for( i = 0 ; i < nLen ; i++ ) + { + const Property aProp = pProps[ i ]; + + // Naechste Passende Methode in der Liste suchen + while( pPropertyDefs[ iList ].pName ) + { + if( pPropertyDefs[ iList ].nConcept & nConcepts ) + break; + iList++; + } + sal_Int32 iDemanded = iList; + iList++; + + OUString aPropName = aProp.Name; + OString aNameStr( aPropName.getStr(), aPropName.getLength(), RTL_TEXTENCODING_ASCII_US ); + //UStringToString(aPropName, CHARSET_SYSTEM); + +//printf( "Property = %s\n", aNameStr.getStr() ); + + OString aDemandedName = pPropertyDefs[ iDemanded ].pName; + //OString aDemandedName = pDemandedPropNames[ i ]; + aErrorStr = "Expected property \""; + aErrorStr += aDemandedName; + aErrorStr += "\", found \""; + aErrorStr += aNameStr; + aErrorStr += "\""; + TEST_ENSHURE( aNameStr == aDemandedName, aErrorStr.getStr() ); + // cout << "Property " << (i+1) << ": \"" << (const char*)UStringToString(aPropName, CHARSET_SYSTEM) << "\""; + + + Type aPropType = aProp.Type; + OString aTypeNameStr( OUStringToOString(aPropType.getTypeName(), RTL_TEXTENCODING_ASCII_US) ); + //Reference< XIdlClass > xPropType = aProp.Type; + //OString aTypeNameStr( xPropType->getName(), xPropType->getName().getLength(), RTL_TEXTENCODING_ASCII_US ); + OString aDemandedTypeNameStr = pDemandedPropTypes[ iDemanded ]; + //OString aDemandedTypeNameStr = pDemandedPropTypes[ i ]; + aErrorStr = "Property \""; + aErrorStr += aDemandedName; + aErrorStr += "\", expected type >"; + aErrorStr += aDemandedTypeNameStr; + aErrorStr += "< found type >"; + aErrorStr += aTypeNameStr; + aErrorStr += "<"; + TEST_ENSHURE( aTypeNameStr == aDemandedTypeNameStr, aErrorStr.getStr() ); + // cout << " (Prop-Typ: " << (const char*)UStringToString(xPropType->getName(), CHARSET_SYSTEM) << ")"; + + // Wert des Property lesen und ausgeben + aPropVal = xPropSet->getPropertyValue( aPropName ); + // cout << "\n\tWert = " << (const char*)UStringToString(AnyToString( aPropVal, sal_True ), CHARSET_SYSTEM); + + OString aValStr = OUStringToOString( AnyToString( aPropVal, sal_False, xMgr ), RTL_TEXTENCODING_ASCII_US ); + OString aDemandedValStr = pDemandedPropVals[ iDemanded ]; + //OString aDemandedValStr = pDemandedPropVals[ i ]; + aErrorStr = "Property \""; + aErrorStr += aDemandedName; + aErrorStr += "\", expected val >"; + aErrorStr += aDemandedValStr; + aErrorStr += "< found val >"; + aErrorStr += aValStr; + aErrorStr += "<"; + TEST_ENSHURE( aValStr == aDemandedValStr, aErrorStr.getStr() ); + + // Wert pruefen und typgerecht modifizieren + TypeClass eType = aPropVal.getValueType().getTypeClass(); + //Reference< XIdlClass > xIdlClass = aPropVal.getReflection()->getIdlClass(); + //TypeClass eType = xIdlClass->getTypeClass(); + Any aNewVal; + sal_Bool bModify = sal_True; + switch( eType ) + { + case TypeClass_STRING: + { + OUString aStr; + aPropVal >>= aStr; + //OString aStr = aPropVal.getString(); + aStr = aStr + OUString::createFromAscii(" (Modified!)"); + aNewVal <<= aStr; + break; + } + case TypeClass_DOUBLE: + { + double d(0.0); + aPropVal >>= d; + aNewVal <<= d + 1.0; + break; + } + case TypeClass_SHORT: + { + sal_Int16 n(0); + aPropVal >>= n; + aNewVal <<= sal_Int16( n + 1 ); + break; + } + case TypeClass_LONG: + { + sal_Int32 n(0); + aPropVal >>= n; + aNewVal <<= sal_Int32( n + 1 ); + break; + } + default: + bModify = sal_False; + break; + } + + // Modifizieren nur beim letzten Durchlauf + if( nConcepts == 15 ) + { + // XExactName pruefen, dafuer alles gross machen + // (Introspection ist mit LowerCase implementiert, also anders machen) + OUString aUpperUStr = aPropName.toAsciiUpperCase(); + OUString aExactName = xExactName->getExactName( aUpperUStr ); + if( aExactName != aPropName ) + { + aErrorStr = "Property \""; + aErrorStr += OUStringToOString( aPropName, RTL_TEXTENCODING_ASCII_US ); + aErrorStr += "\", not found as \""; + aErrorStr += OUStringToOString(aUpperUStr, RTL_TEXTENCODING_ASCII_US ); + aErrorStr += "\" using XExactName"; + TEST_ENSHURE( sal_False, aErrorStr.getStr() ); + } + } + else + { + bModify = sal_False; + } + + // Neuen Wert setzen, wieder lesen und ausgeben + if( bModify ) + { + // cout.flush(); + + // 1.7.1999, UnknownPropertyException bei ReadOnly-Properties abfangen + try + { + xPropSet->setPropertyValue( aPropName, aNewVal ); + } + catch(UnknownPropertyException e1) + { + } + + aPropVal = xPropSet->getPropertyValue( aPropName ); + // cout << "\n\tModifizierter Wert = " << (const char*) UStringToString(AnyToString( aPropVal, sal_True ), CHARSET_SYSTEM) << "\n"; + + OUString aStr = AnyToString( aPropVal, sal_False, xMgr ); + OString aModifiedValStr = OUStringToOString( aStr, RTL_TEXTENCODING_ASCII_US ); + OString aDemandedModifiedValStr = pDemandedModifiedPropVals[ i ]; + aErrorStr = "Property \""; + aErrorStr += aDemandedName; + aErrorStr += "\", expected modified val >"; + aErrorStr += aDemandedModifiedValStr; + aErrorStr += "< found val >"; + aErrorStr += aModifiedValStr; + aErrorStr += "<"; + TEST_ENSHURE( aModifiedValStr == aDemandedModifiedValStr, aErrorStr.getStr() ); + } + else + { + // cout << "\n\tWert wurde nicht modifiziert\n"; + } + + // Checken, ob alle Properties auch einzeln gefunden werden + aErrorStr = "property \""; + aErrorStr += aDemandedName; + aErrorStr += "\" not found with hasProperty()"; + OUString aWDemandedName = OStringToOUString(aDemandedName, RTL_TEXTENCODING_ASCII_US ); + sal_Bool bProperty = xAccess->hasProperty( aWDemandedName, nConcepts ); + //sal_Bool bProperty = xAccess->hasProperty( aWDemandedName, PropertyConcept::ALL - PropertyConcept::DANGEROUS ); + TEST_ENSHURE( bProperty, aErrorStr.getStr() ); + + aErrorStr = "property \""; + aErrorStr += aDemandedName; + aErrorStr += "\" not equal to same Property in sequence returned by getProperties()"; + try + { + Property aGetProp = xAccess->getProperty( aWDemandedName, nConcepts ); + //Property aGetProp = xAccess->getProperty( aWDemandedName, PropertyConcept::ALL ); + //TEST_ENSHURE( aGetProp == aProp , aErrorStr.getStr() ); + } + catch (RuntimeException e1) + { + aErrorStr = "property \""; + aErrorStr += aDemandedName; + aErrorStr += "\", exception was thrown when trying getProperty()"; + TEST_ENSHURE( sal_False, aErrorStr.getStr() ); + } + + } + } + } + + // Schleife ueber alle Kombinationen von Concepts + for( sal_Int32 nConcepts = 0 ; nConcepts < 128 ; nConcepts++ ) + { +//printf( "*******************************************************\n" ); +//printf( "nConcepts = %ld\n", nConcepts ); + + // Das 2^6-Bit steht fuer "den Rest" + sal_Int32 nRealConcepts = nConcepts; + if( nConcepts & 0x40 ) + nRealConcepts |= (0xFFFFFFFF - 0x3F); + + // Wieviele Methoden sollten es sein + sal_Int32 nDemandedMethCount = 0; + sal_Int32 iList = 0; + while( pMethodDefs[ iList ].pName ) + { + if( pMethodDefs[ iList ].nConcept & nRealConcepts ) + nDemandedMethCount++; + iList++; + } + + // Methoden-Array ausgeben + //aMethodSeq = xAccess->getMethods + Sequence< Reference< XIdlMethod > > aMethodSeq = xAccess->getMethods( nRealConcepts ); + //Sequence<XIdlMethodRef> aMethodSeq = xAccess->getMethods + // ( MethodConcept::ALL - MethodConcept::DANGEROUS - MethodConcept::PROPERTY ); + sal_Int32 nLen = aMethodSeq.getLength(); + // cout << "\n\n*** Methoden ***\n"; + // cout << "Introspection hat " << nLen << " Methoden gefunden:\n"; + + aErrorStr = "Expected to find "; + aErrorStr += OString::valueOf( nDemandedMethCount ); + aErrorStr += " methods but found "; + aErrorStr += OString::valueOf( nLen ); + TEST_ENSHURE( nLen == nDemandedMethCount, aErrorStr.getStr() ); + + const Reference< XIdlMethod >* pMethods = aMethodSeq.getConstArray(); + sal_Int32 i; + iList = 0; + + for( i = 0 ; i < nLen ; i++ ) + { + // Methode ansprechen + const Reference< XIdlMethod >& rxMethod = pMethods[i]; + + // Methode ausgeben + OUString aMethName = rxMethod->getName(); + OString aNameStr = OUStringToOString(aMethName, RTL_TEXTENCODING_ASCII_US ); + +//printf( "Method = %s\n", aNameStr.getStr() ); + + // Naechste Passende Methode in der Liste suchen + while( pMethodDefs[ iList ].pName ) + { + if( pMethodDefs[ iList ].nConcept & nRealConcepts ) + break; + iList++; + } + OString aDemandedName = pMethodDefs[ iList ].pName; + iList++; + + //OString aDemandedName = pDemandedMethNames[ i ]; + aErrorStr = "Expected method \""; + aErrorStr += aDemandedName; + aErrorStr += "\", found \""; + aErrorStr += aNameStr; + aErrorStr += "\""; + TEST_ENSHURE( aNameStr == aDemandedName, aErrorStr.getStr() ); + // cout << "Methode " << (i+1) << ": " << (const char*) UStringToString(rxMethod->getReturnType()->getName(), CHARSET_SYSTEM) + // << " " << (const char*) UStringToString(rxMethod->getName(), CHARSET_SYSTEM) << "( "; + + // Checken, ob alle Methoden auch einzeln gefunden werden + aErrorStr = "method \""; + aErrorStr += aDemandedName; + aErrorStr += "\" not found with hasMethod()"; + OUString aWDemandedName = OStringToOUString(aDemandedName, RTL_TEXTENCODING_ASCII_US ); + sal_Bool bMethod = xAccess->hasMethod( aWDemandedName, nRealConcepts ); + //sal_Bool bMethod = xAccess->hasMethod( aWDemandedName, MethodConcept::ALL ); + TEST_ENSHURE( bMethod, aErrorStr.getStr() ); + + aErrorStr = "method \""; + aErrorStr += aDemandedName; + aErrorStr += "\" not equal to same method in sequence returned by getMethods()"; + try + { + Reference< XIdlMethod > xGetMethod = xAccess->getMethod( aWDemandedName, nRealConcepts ); + //XIdlMethodRef xGetMethod = xAccess->getMethod( aWDemandedName, MethodConcept::ALL ); + TEST_ENSHURE( xGetMethod == rxMethod , aErrorStr.getStr() ); + } + catch (RuntimeException e1) + { + aErrorStr = "method \""; + aErrorStr += aDemandedName; + aErrorStr += "\", exception was thrown when trying getMethod()"; + TEST_ENSHURE( sal_False, aErrorStr.getStr() ); + } + } + } + + // Listener-Klassen ausgeben + Sequence< Type > aClassSeq = xAccess->getSupportedListeners(); + sal_Int32 nLen = aClassSeq.getLength(); + // cout << "\n\n*** Anmeldbare Listener ***\n"; + // cout << "Introspection hat " << nLen << " Listener gefunden:\n"; + + const Type* pListeners = aClassSeq.getConstArray(); + for( sal_Int32 i = 0 ; i < nLen ; i++ ) + { + // Methode ansprechen + const Type& aListenerType = pListeners[i]; + + // Namen besorgen + OUString aListenerClassName = aListenerType.getTypeName(); + // cout << "Listener " << (i+1) << ": " << (const char*)UStringToString(aListenerClassName, CHARSET_SYSTEM) << "\n"; + } + + + // Performance bei hasMethod testen. + //CheckMethodPerformance( xAccess, "queryInterface", 100000 ); + //CheckMethodPerformance( xAccess, "getIdlClasses", 100000 ); + + // cout.flush(); + + + + + return sal_True; +} + + +SAL_IMPLEMENT_MAIN() +{ + Reference< XMultiServiceFactory > xMgr( createRegistryServiceFactory( OUString::createFromAscii("stoctest.rdb") ) ); + + sal_Bool bSucc = sal_False; + try + { + Reference< XImplementationRegistration > xImplReg( + xMgr->createInstance( OUString::createFromAscii("com.sun.star.registry.ImplementationRegistration") ), UNO_QUERY ); + OSL_ENSURE( xImplReg.is(), "### no impl reg!" ); + + // Register services + OUString libName( RTL_CONSTASCII_USTRINGPARAM( + "reflection.uno" SAL_DLLEXTENSION) ); +// ORealDynamicLoader::computeLibraryName( OUString::createFromAscii("corefl"), libName); + fprintf(stderr, "1\n" ); + xImplReg->registerImplementation(OUString::createFromAscii("com.sun.star.loader.SharedLibrary"), + libName, Reference< XSimpleRegistry >() ); + fprintf(stderr, "2\n" ); + Reference< XIdlReflection > xRefl( xMgr->createInstance( OUString::createFromAscii("com.sun.star.reflection.CoreReflection") ), UNO_QUERY ); + OSL_ENSURE( xRefl.is(), "### no corereflection!" ); + + // Introspection + libName = OUString::createFromAscii( + "introspection.uno" SAL_DLLEXTENSION); +// ORealDynamicLoader::computeLibraryName( OUString::createFromAscii("insp"), libName); + fprintf(stderr, "3\n" ); + xImplReg->registerImplementation(OUString::createFromAscii("com.sun.star.loader.SharedLibrary"), + libName, Reference< XSimpleRegistry >() ); + fprintf(stderr, "4\n" ); + Reference< XIntrospection > xIntrosp( xMgr->createInstance( OUString::createFromAscii("com.sun.star.beans.Introspection") ), UNO_QUERY ); + OSL_ENSURE( xRefl.is(), "### no corereflection!" ); + + fprintf(stderr, "before test_introsp\n" ); + bSucc = test_introsp( xMgr, xRefl, xIntrosp ); + fprintf(stderr, "after test_introsp\n" ); + //bSucc = test_corefl( xRefl ); + } + catch (Exception & rExc) + { + OSL_ENSURE( sal_False, "### exception occured!" ); + OString aMsg( OUStringToOString( rExc.Message, RTL_TEXTENCODING_ASCII_US ) ); + OSL_TRACE( "### exception occured: " ); + OSL_TRACE( aMsg.getStr() ); + OSL_TRACE( "\n" ); + } + + Reference< XComponent >( xMgr, UNO_QUERY )->dispose(); + + printf( "testintrosp %s !\n", (bSucc ? "succeeded" : "failed") ); + return (bSucc ? 0 : -1); +} + + + + + + + +//***************************** +//*** TEST-Implementationen *** +//***************************** +// Bleibt auf Dauer nicht drin, dient als exportierbare Test-Klasse +// z.B. fuer Basic-Anbindung + + + + + + diff --git a/stoc/test/testintrosp.idl b/stoc/test/testintrosp.idl new file mode 100644 index 000000000000..d2d01cbb692d --- /dev/null +++ b/stoc/test/testintrosp.idl @@ -0,0 +1,220 @@ +/************************************************************************* + * + * 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 __com_sun_star_beans_XIntroTest_idl__ +#define __com_sun_star_beans_XIntroTest_idl__ + +#ifndef __com_sun_star_uno_XInterface_idl__ +#include <com/sun/star/uno/XInterface.idl> +#endif + +#ifndef __com_sun_star_beans_Property_idl__ +#include <com/sun/star/beans/Property.idl> +#endif + +#ifndef __com_sun_star_beans_PropertyValue_idl__ +#include <com/sun/star/beans/PropertyValue.idl> +#endif + +#ifndef __com_sun_star_uno_TypeClass_idl__ +#include <com/sun/star/uno/TypeClass.idl> +#endif + +#ifndef __com_sun_star_beans_XPropertiesChangeListener_idl__ +#include <com/sun/star/beans/XPropertiesChangeListener.idl> +#endif + + +//============================================================================= + +module ModuleA +{ +//module com { module sun { module star { module beans { + +//interface XPropertyChangeListener; +//interface XPropertiesChangeListener; + +//============================================================================= +/** This is a test interface for introspection. + + <p>IMPORTANT: FOR TEST ONLY! + + <p>The following interface is just for testing purposes. It will not + stay in the product. It is only used as an exportable test class, + i.e. for BASIC integration. + + @deprecated +*/ +interface XIntroTest: com::sun::star::uno::XInterface +{ + //------------------------------------------------------------------------- + /** contains the ID-String of the implementation. + */ + [attribute] string ObjectName; + + //------------------------------------------------------------------------- + /** contains the first name of a person. + */ + [readonly, attribute] string FirstName; + + //------------------------------------------------------------------------- + /** contains the last name of a person. + */ + [readonly, attribute] string LastName; + + //------------------------------------------------------------------------- + /** contains the age of a person. + */ + [readonly, attribute] short Age; + + //------------------------------------------------------------------------- + /** contains the number of children person has. + */ + [attribute] short ChildrenCount; + + //------------------------------------------------------------------------- + /** contains a struct of type Property. + */ + [attribute] com::sun::star::beans::Property FirstStruct; + + //------------------------------------------------------------------------- + /** contains a struct of type PropertyValue. + */ + [attribute] com::sun::star::beans::PropertyValue SecondStruct; + + //------------------------------------------------------------------------- + /** Ausgabe-Methode + */ + void writeln( [in] string Text ); + + //------------------------------------------------------------------------- + /** ... + */ + long getDroenk(); + + //------------------------------------------------------------------------- + /** Weitere Introspection-Test-Objekt holen + */ + XIntroTest getIntroTest(); + //com::sun::star::beans::XIntroTest getIntroTest(); + + //------------------------------------------------------------------------- + /** !!! No property, because parameter exists + */ + long getUps( [in] long l ); + + //------------------------------------------------------------------------- + /** ... + */ + void setDroenk( [in] long l ); + + //------------------------------------------------------------------------- + /** ... + */ + short getBla(); + + //------------------------------------------------------------------------- + /** !!! Not the set method for property Bla, because param type != return type. + */ + void setBla( [in] long n ); + + //------------------------------------------------------------------------- + /** ... + */ + short getBlub(); + + //------------------------------------------------------------------------- + /** ... + */ + void setBlub( [in] short n ); + + //------------------------------------------------------------------------- + /** ... + */ + short getGulp(); + + //------------------------------------------------------------------------- + /** !!! Not the set method for property Gulp, because return type != void. + */ + short setGulp( [in] short n ); + + //------------------------------------------------------------------------- + /** ... + */ + com::sun::star::uno::TypeClass getTypeClass( [in] short n ); + + //------------------------------------------------------------------------- + /** ... + */ + void setTypeClass( [in] com::sun::star::uno::TypeClass t, + [in] double d1, + [in] double d2 ); + + //------------------------------------------------------------------------- + /** + */ + sequence<string> getStrings(); + + //------------------------------------------------------------------------- + /** ... + */ + void setStrings( [in] sequence<string> Strings ); + + //------------------------------------------------------------------------- + /** ... + */ + void setStringsPerMethod( [in] sequence<string> Strings, + [in] short n ); + + //------------------------------------------------------------------------- + /** + */ + sequence< sequence< sequence< short > > > getMultiSequence(); + + //------------------------------------------------------------------------- + /** ... + */ + void setMultiSequence( [in] sequence< sequence< sequence< short > > > Seq ); + + //------------------------------------------------------------------------- + /**Add a PropertiesChangeListener + */ + [oneway] void addPropertiesChangeListener( [in] sequence< string > PropertyNames, + [in] com::sun::star::beans::XPropertiesChangeListener Listener ); + + //------------------------------------------------------------------------- + /**Remove a PropertiesChangeListener + */ + [oneway] void removePropertiesChangeListener( [in] com::sun::star::beans::XPropertiesChangeListener Listener ); + +}; + +//============================================================================= + +}; +//}; }; }; }; + +#endif diff --git a/stoc/test/testloader.cxx b/stoc/test/testloader.cxx new file mode 100644 index 000000000000..a0ef275565e0 --- /dev/null +++ b/stoc/test/testloader.cxx @@ -0,0 +1,137 @@ +/************************************************************************* + * + * 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 <stdio.h> + +#include <sal/main.h> +#ifndef _OSL_MODULE_H_ +#include <osl/module.hxx> +#endif +#include <osl/diagnose.h> + +#include <com/sun/star/loader/XImplementationLoader.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/lang/XSingleComponentFactory.hpp> + +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/factory.hxx> + +#if defined ( UNX ) +#include <limits.h> +#define _MAX_PATH PATH_MAX +#endif + +using namespace com::sun::star::uno; +using namespace com::sun::star::loader; +using namespace com::sun::star::lang; +using namespace osl; +using namespace rtl; +using namespace cppu; + +#if OSL_DEBUG_LEVEL > 0 +#define TEST_ENSHURE(c, m) OSL_ENSURE(c, m) +#else +#define TEST_ENSHURE(c, m) OSL_VERIFY(c) +#endif + +class EmptyComponentContext : public WeakImplHelper1< XComponentContext > +{ +public: + virtual Any SAL_CALL getValueByName( const OUString& /*Name*/ ) + throw (RuntimeException) + { + return Any(); + } + virtual Reference< XMultiComponentFactory > SAL_CALL getServiceManager( ) + throw (RuntimeException) + { + return Reference< XMultiComponentFactory > (); + } + +}; + + +SAL_IMPLEMENT_MAIN() +{ + Reference<XInterface> xIFace; + + Module module; + + OUString dllName( + RTL_CONSTASCII_USTRINGPARAM("bootstrap.uno" SAL_DLLEXTENSION) ); + + if (module.load(dllName)) + { + // try to get provider from module + component_getFactoryFunc pCompFactoryFunc = (component_getFactoryFunc) + module.getFunctionSymbol( OUString::createFromAscii(COMPONENT_GETFACTORY) ); + + if (pCompFactoryFunc) + { + XSingleServiceFactory * pRet = (XSingleServiceFactory *)(*pCompFactoryFunc)( + "com.sun.star.comp.stoc.DLLComponentLoader", 0, 0 ); + if (pRet) + { + xIFace = pRet; + pRet->release(); + } + } + } + + TEST_ENSHURE( xIFace.is(), "testloader error1"); + + Reference<XSingleComponentFactory> xFactory( Reference<XSingleComponentFactory>::query(xIFace) ); + + TEST_ENSHURE( xFactory.is(), "testloader error2"); + + Reference<XInterface> xLoader = xFactory->createInstanceWithContext( new EmptyComponentContext ); + + TEST_ENSHURE( xLoader.is(), "testloader error3"); + + Reference<XServiceInfo> xServInfo( Reference<XServiceInfo>::query(xLoader) ); + + TEST_ENSHURE( xServInfo.is(), "testloader error4"); + + TEST_ENSHURE( xServInfo->getImplementationName().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.comp.stoc.DLLComponentLoader") ), "testloader error5"); + TEST_ENSHURE( xServInfo->supportsService(OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.loader.SharedLibrary")) ), "testloader error6"); + TEST_ENSHURE( xServInfo->getSupportedServiceNames().getLength() == 1, "testloader error7"); + + xIFace.clear(); + xFactory.clear(); + xLoader.clear(); + xServInfo.clear(); + + printf("Test Dll ComponentLoader, OK!\n"); + + return(0); +} + + diff --git a/stoc/test/testproxyfac.cxx b/stoc/test/testproxyfac.cxx new file mode 100644 index 000000000000..38ab9eef51d2 --- /dev/null +++ b/stoc/test/testproxyfac.cxx @@ -0,0 +1,379 @@ +/************************************************************************* + * + * 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/main.h" +#include "osl/diagnose.h" +#include "rtl/alloc.h" +#include "uno/environment.hxx" +#include "cppuhelper/servicefactory.hxx" +#include "cppuhelper/implbase1.hxx" +#include "cppuhelper/implbase3.hxx" +#include "com/sun/star/uno/XCurrentContext.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/registry/XSimpleRegistry.hpp" +#include "com/sun/star/registry/XImplementationRegistration.hpp" +#include "com/sun/star/beans/XPropertySet.hpp" +#include "com/sun/star/reflection/XProxyFactory.hpp" + +#include <stdio.h> + + +using namespace ::rtl; +using namespace ::osl; +using namespace ::cppu; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; + + +typedef WeakImplHelper3< lang::XServiceInfo, + XCurrentContext, + reflection::XProxyFactory > t_impl; + +//============================================================================== +class TargetObject : public t_impl +{ +public: + static int s_obj; + + virtual ~TargetObject() { + --s_obj; + OSL_TRACE( "~TargetObject()" ); + } + TargetObject() + { ++s_obj; } + + Any SAL_CALL queryInterface( Type const & type ) + throw (RuntimeException); + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() throw (RuntimeException) + { return OUString::createFromAscii( "target" ); } + virtual sal_Bool SAL_CALL supportsService( const OUString & /*rServiceName*/ ) + throw (RuntimeException) + { return sal_False; } + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() + throw (RuntimeException) + { return Sequence< OUString >(); } + // XProxyFactory + virtual Reference< XAggregation > SAL_CALL createProxy( + const Reference< XInterface > & xTarget ) throw (RuntimeException) + { return Reference< XAggregation >( xTarget, UNO_QUERY ); } + // XCurrentContext + virtual Any SAL_CALL getValueByName( OUString const & name ) + throw (RuntimeException) + { return makeAny( name ); } +}; + +//______________________________________________________________________________ +Any TargetObject::queryInterface( Type const & type ) + throw (RuntimeException) +{ + Any ret( t_impl::queryInterface( type ) ); + if (ret.hasValue()) + return ret; + throw lang::DisposedException( + OUString( RTL_CONSTASCII_USTRINGPARAM("my test exception") ), + static_cast< OWeakObject * >(this) ); +} + +int TargetObject::s_obj = 0; + + +//============================================================================== +class TestMaster : public WeakImplHelper1< lang::XServiceInfo > +{ + Reference< XAggregation > m_xProxyTarget; + Reference<lang::XServiceInfo> m_xOtherProxyTargetBeforeSetDelegator; + + inline TestMaster() { ++s_obj; } +public: + static int s_obj; + static Reference< XInterface > create( + Reference< reflection::XProxyFactory > const & xProxyFac ); + static Reference< XInterface > create( + Reference< XInterface > const & xTarget, + Reference< reflection::XProxyFactory > const & xProxyFac ); + + virtual ~TestMaster() { + --s_obj; + OSL_TRACE( "~TestMaster()" ); + } + + virtual Any SAL_CALL queryInterface( const Type & rType ) + throw (RuntimeException) + { + Any aRet( + WeakImplHelper1< lang::XServiceInfo >::queryInterface( rType ) ); + if (aRet.hasValue()) + return aRet; + return m_xProxyTarget->queryAggregation( rType ); + } + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName() throw (RuntimeException) + { return OUString::createFromAscii( "master" ); } + virtual sal_Bool SAL_CALL supportsService( const OUString & /*rServiceName*/ ) + throw (RuntimeException) + { return sal_False; } + virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() + throw (RuntimeException) + { return Sequence< OUString >(); } +}; + +int TestMaster::s_obj = 0; + + +Reference< XInterface > TestMaster::create( + Reference< XInterface > const & xTarget, + Reference< reflection::XProxyFactory > const & xProxyFac ) +{ + TestMaster * that = new TestMaster; + Reference< XInterface > xRet( static_cast< OWeakObject * >( that ) ); + { + Reference< XAggregation > xAgg( xProxyFac->createProxy( xTarget ) ); + // ownership take over + that->m_xProxyTarget.set( xAgg, UNO_QUERY_THROW ); + that->m_xOtherProxyTargetBeforeSetDelegator.set( + that->m_xProxyTarget, UNO_QUERY ); + } + that->m_xProxyTarget->setDelegator( xRet ); + return xRet; +} + +Reference< XInterface > TestMaster::create( + Reference< reflection::XProxyFactory > const & xProxyFac ) +{ + return create( + static_cast< OWeakObject * >( new TargetObject ), xProxyFac ); +} + + +static void test_proxyfac_( + Reference< XInterface > const & xMaster, OUString const & test, + Reference< reflection::XProxyFactory > const & /*xProxyFac*/ ) +{ + (void)test; + Reference< lang::XServiceInfo > xMaster_XServiceInfo( + xMaster, UNO_QUERY_THROW ); + OSL_ASSERT( xMaster_XServiceInfo->getImplementationName().equals( test ) ); + + Reference< reflection::XProxyFactory > xTarget( xMaster, UNO_QUERY_THROW ); + Reference< XCurrentContext > xTarget_XCurrentContext( + xTarget, UNO_QUERY_THROW ); + Reference< XCurrentContext > xMaster_XCurrentContext( + xMaster, UNO_QUERY_THROW ); + + OSL_ASSERT( + xTarget_XCurrentContext->getValueByName( test ) == makeAny( test ) ); + OSL_ASSERT( + xMaster_XCurrentContext->getValueByName( test ) == makeAny( test ) ); + + Reference< XAggregation > xFakeAgg( xTarget->createProxy( xTarget ) ); + if (xFakeAgg.is()) + { + OSL_ASSERT( xTarget == xFakeAgg ); + OSL_ASSERT( xMaster == xFakeAgg ); + } + + Reference< lang::XServiceInfo > xTarget_XServiceInfo( + xTarget, UNO_QUERY_THROW ); + OSL_ASSERT( xTarget_XServiceInfo->getImplementationName().equals( test ) ); + Reference< lang::XServiceInfo > xTarget_XServiceInfo2( + xTarget, UNO_QUERY_THROW ); + OSL_ASSERT( xTarget_XServiceInfo2.get() == xTarget_XServiceInfo.get() ); + + OSL_ASSERT( xTarget == xTarget_XCurrentContext ); + OSL_ASSERT( xTarget_XCurrentContext == xMaster ); + OSL_ASSERT( + xTarget_XCurrentContext.get() == xMaster_XCurrentContext.get() ); + OSL_ASSERT( xTarget_XCurrentContext == xMaster ); + OSL_ASSERT( xTarget == xMaster ); + OSL_ASSERT( xTarget_XServiceInfo.get() == xMaster_XServiceInfo.get() ); + OSL_ASSERT( xTarget_XServiceInfo == xMaster ); + OSL_ASSERT( xMaster_XServiceInfo == xMaster ); + + try + { + Reference< registry::XRegistryKey >( + xMaster, UNO_QUERY_THROW ); + } + catch (lang::DisposedException & exc) + { + if (! exc.Message.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM("my test exception") )) + throw; + } +} + +static void test_proxyfac( + Reference< XInterface > const & xMaster, OUString const & test, + Reference< reflection::XProxyFactory > const & xProxyFac ) +{ + test_proxyfac_( xMaster, test, xProxyFac ); + // proxy the proxy... + Reference< XInterface > xNew( TestMaster::create( xMaster, xProxyFac ) ); + test_proxyfac_( + xNew, OUString( RTL_CONSTASCII_USTRINGPARAM("master") ), xProxyFac ); +} + +SAL_IMPLEMENT_MAIN() +{ + bool success = true; + + Environment cpp_env; + OUString cpp( RTL_CONSTASCII_USTRINGPARAM( + CPPU_CURRENT_LANGUAGE_BINDING_NAME) ); + uno_getEnvironment( + reinterpret_cast< uno_Environment ** >( &cpp_env ), + cpp.pData, 0 ); + OSL_ENSURE( cpp_env.is(), "### cannot get C++ uno env!" ); + + { + Reference< lang::XMultiServiceFactory > xMgr( + createRegistryServiceFactory( + OUString( RTL_CONSTASCII_USTRINGPARAM("stoctest.rdb") ) ) ); + + try + { + Reference< registry::XImplementationRegistration > xImplReg( + xMgr->createInstance( + OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.registry.ImplementationRegistration") + ) ), + UNO_QUERY ); + OSL_ENSURE( xImplReg.is(), "### no impl reg!" ); + + OUString aLibName( + RTL_CONSTASCII_USTRINGPARAM("proxyfac.uno" SAL_DLLEXTENSION) ); + xImplReg->registerImplementation( + OUString( + RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.loader.SharedLibrary") ), + aLibName, Reference< registry::XSimpleRegistry >() ); + + Reference< reflection::XProxyFactory > xProxyFac( + xMgr->createInstance( + OUString::createFromAscii( + "com.sun.star.reflection.ProxyFactory") ), + UNO_QUERY_THROW ); + + Reference< XAggregation > x( + xProxyFac->createProxy( + static_cast< OWeakObject * >( new TargetObject ) ) ); + // no call + + { + Reference< XInterface > xMaster( TestMaster::create( xProxyFac ) ); + test_proxyfac( + xMaster, + OUString( RTL_CONSTASCII_USTRINGPARAM("master") ), + xProxyFac ); + } + { + Reference< XInterface > xMaster( TestMaster::create( xProxyFac ) ); + // no call + } + + { + Reference< XInterface > xMaster( TestMaster::create( xProxyFac ) ); + Reference< reflection::XProxyFactory > xSlave_lives_alone( + xMaster, UNO_QUERY_THROW ); + xMaster.clear(); + test_proxyfac( + xSlave_lives_alone, + OUString( RTL_CONSTASCII_USTRINGPARAM("master") ), + xProxyFac ); + uno_dumpEnvironment( stdout, cpp_env.get(), 0 ); + } + { + Reference< XInterface > xMaster( TestMaster::create( xProxyFac ) ); + Reference< reflection::XProxyFactory > xSlave_lives_alone( + xMaster, UNO_QUERY_THROW ); + // no call + } + + test_proxyfac( + xProxyFac->createProxy( + static_cast< OWeakObject * >( new TargetObject ) ), + OUString( RTL_CONSTASCII_USTRINGPARAM("target") ), + xProxyFac ); + uno_dumpEnvironment( stdout, cpp_env.get(), 0 ); + } + catch (Exception & rExc) + { + (void)rExc; + OSL_ENSURE( + ! __FILE__, + OUStringToOString( + rExc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); + success = false; + } + + + Reference< lang::XComponent > xComp; + Reference< beans::XPropertySet >( + xMgr, UNO_QUERY_THROW )->getPropertyValue( + OUString( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) + >>= xComp; + xComp->dispose(); + } + + if (TestMaster::s_obj != 0) + fprintf( stderr, "TestMaster objects: %d\n", TestMaster::s_obj ); + if (TargetObject::s_obj != 0) + fprintf( stderr, "TargetObject objects: %d\n", TargetObject::s_obj ); + + uno_dumpEnvironment( stdout, cpp_env.get(), 0 ); + void ** ppInterfaces; + sal_Int32 len; + uno_ExtEnvironment * env = cpp_env.get()->pExtEnv; + (*env->getRegisteredInterfaces)( + env, &ppInterfaces, &len, rtl_allocateMemory ); + if (len != 0) + fprintf( stderr, "%d registered C++ interfaces left!\n", len ); + + success &= (TestMaster::s_obj == 0 && + TargetObject::s_obj == 0 && + len == 0); + if (success) + { + printf( "testproxyfac succeeded.\n" ); + return 0; + } + else + { + fprintf( stderr, "testproxyfac failed!\n" ); + return 1; + } +} + diff --git a/stoc/test/testregistry.cxx b/stoc/test/testregistry.cxx new file mode 100644 index 000000000000..7be7136933e7 --- /dev/null +++ b/stoc/test/testregistry.cxx @@ -0,0 +1,696 @@ +/************************************************************************* + * + * 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <sal/main.h> +#include <osl/module.hxx> +#include <osl/diagnose.h> +#include <osl/process.h> +#include <registry/registry.hxx> + + +#include <com/sun/star/registry/XSimpleRegistry.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <cppuhelper/factory.hxx> +#include <cppuhelper/bootstrap.hxx> +#include <cppuhelper/servicefactory.hxx> + +#include <com/sun/star/lang/XComponent.hpp> + +#if defined ( UNX ) +#include <limits.h> +#define _MAX_PATH PATH_MAX +#endif + +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::registry; +using namespace com::sun::star::lang; +using namespace com::sun::star::beans; +using namespace rtl; +using namespace osl; + +#if OSL_DEBUG_LEVEL > 0 +#define TEST_ENSHURE(c, m) OSL_ENSURE(c, m) +#else +#define TEST_ENSHURE(c, m) OSL_VERIFY(c) +#endif + +namespace stoc_impreg +{ +void SAL_CALL mergeKeys( + Reference< registry::XRegistryKey > const & xDest, + Reference< registry::XRegistryKey > const & xSource ) + SAL_THROW( (registry::InvalidRegistryException, registry::MergeConflictException) ); +} +static void mergeKeys( + Reference< registry::XSimpleRegistry > const & xDest, + OUString const & rBaseNode, + OUString const & rURL ) + SAL_THROW( (registry::InvalidRegistryException, registry::MergeConflictException) ) +{ + Reference< registry::XRegistryKey > xDestRoot( xDest->getRootKey() ); + Reference< registry::XRegistryKey > xDestKey; + if (rBaseNode.getLength()) + { + xDestKey = xDestRoot->createKey( rBaseNode ); + xDestRoot->closeKey(); + } + else + { + xDestKey = xDestRoot; + } + Reference< registry::XSimpleRegistry > xSimReg( ::cppu::createSimpleRegistry() ); + xSimReg->open( rURL, sal_True, sal_False ); + OSL_ASSERT( xSimReg->isValid() ); + Reference< registry::XRegistryKey > xSourceKey( xSimReg->getRootKey() ); + ::stoc_impreg::mergeKeys( xDestKey, xSourceKey ); + xSourceKey->closeKey(); + xSimReg->close(); + xDestKey->closeKey(); +} + + +OString userRegEnv("STAR_USER_REGISTRY="); + +OUString getExePath() +{ + OUString exe; + OSL_VERIFY( osl_getExecutableFile( &exe.pData ) == osl_Process_E_None); +#if defined(WIN32) || defined(__OS2__) || defined(WNT) + exe = exe.copy(0, exe.getLength() - 16); +#else + exe = exe.copy(0, exe.getLength() - 12); +#endif + return exe; +} + +void setStarUserRegistry() +{ + Registry *myRegistry = new Registry(); + + RegistryKey rootKey, rKey, rKey2; + + OUString userReg = getExePath(); + userReg += OUString::createFromAscii("user.rdb"); + if(myRegistry->open(userReg, REG_READWRITE)) + { + TEST_ENSHURE(!myRegistry->create(userReg), "setStarUserRegistry error 1"); + } + + TEST_ENSHURE(!myRegistry->close(), "setStarUserRegistry error 9"); + delete myRegistry; + + userRegEnv += OUStringToOString(userReg, RTL_TEXTENCODING_ASCII_US); + putenv((char *)userRegEnv.getStr()); +} + +void setLinkInDefaultRegistry(const OUString& linkName, const OUString& linkTarget) +{ + Registry *myRegistry = new Registry(); + + RegistryKey rootKey; + + OUString appReg = getExePath(); + appReg += OUString::createFromAscii("stoctest.rdb"); + + TEST_ENSHURE(!myRegistry->open(appReg, REG_READWRITE), "setLinkInDefaultRegistry error 1"); + TEST_ENSHURE(!myRegistry->openRootKey(rootKey), "setLinkInDefaultRegistry error 2"); + + TEST_ENSHURE(!rootKey.createLink(linkName, linkTarget), "setLinkInDefaultRegistry error 3"); + + TEST_ENSHURE(!rootKey.closeKey(), "setLinkInDefaultRegistry error 4"); + TEST_ENSHURE(!myRegistry->close(), "setLinkInDefaultRegistry error 5"); + + delete myRegistry; +} + + +void test_SimpleRegistry( + OUString const & testreg, + OUString const & testreg2, + bool bMergeDifferently = true ) +{ + Reference<XInterface> xIFace; + Module module; + + OUString dllName( + RTL_CONSTASCII_USTRINGPARAM("simplereg.uno" SAL_DLLEXTENSION) ); + + if (module.load(dllName)) + { + // try to get provider from module + component_getFactoryFunc pCompFactoryFunc = (component_getFactoryFunc) + module.getFunctionSymbol( OUString::createFromAscii(COMPONENT_GETFACTORY) ); + + if (pCompFactoryFunc) + { + XSingleServiceFactory * pRet = (XSingleServiceFactory *) + (*pCompFactoryFunc)( + "com.sun.star.comp.stoc.SimpleRegistry", 0, 0 ); + if (pRet) + { + xIFace = pRet; + pRet->release(); + } + } + } + + TEST_ENSHURE( xIFace.is(), "test_SimpleRegistry error1"); + + Reference<XSingleServiceFactory> xFactory( Reference<XSingleServiceFactory>::query(xIFace) ); + xIFace.clear(); + + TEST_ENSHURE( xFactory.is(), "testloader error11"); + + Reference<XInterface> xIFace2 = xFactory->createInstance(); + xFactory.clear(); + + TEST_ENSHURE( xIFace2.is(), "testloader error12"); + + Reference<XServiceInfo> xServInfo( Reference<XServiceInfo>::query(xIFace2) ); + + TEST_ENSHURE( xServInfo.is(), "test_SimpleRegistry error2"); + + TEST_ENSHURE( xServInfo->getImplementationName().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("com.sun.star.comp.stoc.SimpleRegistry") ), "test_SimpleRegistry error3"); + TEST_ENSHURE( xServInfo->supportsService(OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.registry.SimpleRegistry"))), "test_SimpleRegistry error4"); + TEST_ENSHURE( xServInfo->getSupportedServiceNames().getLength() == 1, "test_SimpleRegistry error5"); + xServInfo.clear(); + + Reference<XSimpleRegistry> xReg( Reference<XSimpleRegistry>::query(xIFace2) ); + xIFace2.clear(); + + TEST_ENSHURE( xReg.is(), "test_SimpleRegistry error6"); + + try + { + xReg->open(testreg, sal_False, sal_True); + + TEST_ENSHURE( xReg->isValid() != sal_False, "test_SimpleRegistry error 7" ); + TEST_ENSHURE( xReg->isReadOnly() == sal_False, "test_SimpleRegistry error 8" ); + + Reference<XRegistryKey> xRootKey(xReg->getRootKey()); + TEST_ENSHURE( xRootKey->isValid(), "test_SimpleRegistry error 9" ); + + Reference<XRegistryKey> xKey = xRootKey->createKey(OUString( RTL_CONSTASCII_USTRINGPARAM("FirstKey") )); + + Reference<XRegistryKey> xSubKey = xKey->createKey(OUString( RTL_CONSTASCII_USTRINGPARAM("FirstSubKey") )); + xSubKey->setLongValue(123456789); + + xSubKey = xKey->createKey(OUString( RTL_CONSTASCII_USTRINGPARAM("SecondSubKey") )); + xSubKey->setAsciiValue(OUString( RTL_CONSTASCII_USTRINGPARAM("ich bin ein acsii value") )); + + xSubKey = xKey->createKey(OUString( RTL_CONSTASCII_USTRINGPARAM("ThirdSubKey") )); + xSubKey->setStringValue(OUString( RTL_CONSTASCII_USTRINGPARAM("ich bin ein unicode value") )); + + xSubKey = xKey->createKey(OUString( RTL_CONSTASCII_USTRINGPARAM("FourthSubKey") )); + Sequence<sal_Int8> aSeq((sal_Int8*)"ich bin ein binary value", 25); + xSubKey->setBinaryValue(aSeq); + + Sequence<OUString> seqNames = xKey->getKeyNames(); + Sequence< Reference<XRegistryKey> > seqKeys = xKey->openKeys(); + + OUString name; + for (sal_Int32 i=0; i < seqNames.getLength(); i++) + { + name = seqNames.getArray()[i]; + xSubKey = seqKeys.getArray()[i]; + + if (name == OUString( RTL_CONSTASCII_USTRINGPARAM("/FirstKey/FirstSubKey") )) + { + TEST_ENSHURE( xSubKey->getLongValue() == 123456789, + "test_SimpleRegistry error 10" ); + } else + if (name == OUString( RTL_CONSTASCII_USTRINGPARAM("/FirstKey/SecondSubKey") )) + { + TEST_ENSHURE( xSubKey->getAsciiValue() == OUString( RTL_CONSTASCII_USTRINGPARAM("ich bin ein acsii value") ), + "test_SimpleRegistry error 11" ); + } else + if (name == OUString( RTL_CONSTASCII_USTRINGPARAM("/FirstKey/ThirdSubKey") )) + { + TEST_ENSHURE( xSubKey->getStringValue() == OUString( RTL_CONSTASCII_USTRINGPARAM("ich bin ein unicode value") ), + "test_SimpleRegistry error 12" ); + } else + if (name == OUString( RTL_CONSTASCII_USTRINGPARAM("/FirstKey/FourthSubKey") )) + { + Sequence<sal_Int8> seqByte = xSubKey->getBinaryValue(); + TEST_ENSHURE(!strcmp(((const char*)seqByte.getArray()), "ich bin ein binary value"), + "test_SimpleRegistry error 13" ); + } + + seqKeys.getArray()[i]->closeKey(); + } + + xKey->closeKey(); + + xRootKey->deleteKey(OUString( RTL_CONSTASCII_USTRINGPARAM("FirstKey") )); + xRootKey->createKey(OUString( RTL_CONSTASCII_USTRINGPARAM("SecondFirstKey" ))); + + xKey = xRootKey->createKey(OUString( RTL_CONSTASCII_USTRINGPARAM("SecondKey") )); + sal_Int32 pLongs[3] = {123, 456, 789}; + Sequence<sal_Int32> seqLongs(pLongs, 3); + xKey->setLongListValue(seqLongs); + + Sequence<sal_Int32> seqLongs2; + seqLongs2 = xKey->getLongListValue(); + TEST_ENSHURE( seqLongs.getLength() == 3, "test_SimpleRegistry error 14" ); + TEST_ENSHURE( seqLongs.getArray()[0] == 123, "test_SimpleRegistry error 15" ); + TEST_ENSHURE( seqLongs.getArray()[1] == 456, "test_SimpleRegistry error 16" ); + TEST_ENSHURE( seqLongs.getArray()[2] == 789, "test_SimpleRegistry error 17" ); + + + xKey = xRootKey->createKey(OUString( RTL_CONSTASCII_USTRINGPARAM("ThirdKey") )); + OUString pAscii[3]; + pAscii[0] = OUString( RTL_CONSTASCII_USTRINGPARAM("Hallo") ); + pAscii[1] = OUString( RTL_CONSTASCII_USTRINGPARAM("jetzt komm") ); + pAscii[2] = OUString( RTL_CONSTASCII_USTRINGPARAM("ich") ); + + Sequence<OUString> seqAscii(pAscii, 3); + xKey->setAsciiListValue(seqAscii); + + Sequence<OUString> seqAscii2; + seqAscii2 = xKey->getAsciiListValue(); + TEST_ENSHURE( seqAscii2.getLength() == 3, "test_SimpleRegistry error 18" ); + TEST_ENSHURE( seqAscii2.getArray()[0] == OUString( RTL_CONSTASCII_USTRINGPARAM("Hallo") ), "test_SimpleRegistry error 19"); + TEST_ENSHURE( seqAscii2.getArray()[1] == OUString( RTL_CONSTASCII_USTRINGPARAM("jetzt komm") ), "test_SimpleRegistry error 20"); + TEST_ENSHURE( seqAscii2.getArray()[2] == OUString( RTL_CONSTASCII_USTRINGPARAM("ich") ), "test_SimpleRegistry error 21"); + + xKey = xRootKey->createKey(OUString( RTL_CONSTASCII_USTRINGPARAM("FourthKey") )); + OUString pUnicode[3]; + pUnicode[0] = OUString( RTL_CONSTASCII_USTRINGPARAM("Hallo") ); + pUnicode[1] = OUString( RTL_CONSTASCII_USTRINGPARAM("jetzt komm") ); + pUnicode[2] = OUString( RTL_CONSTASCII_USTRINGPARAM("ich als unicode") ); + + Sequence<OUString> seqUnicode(pUnicode, 3); + xKey->setStringListValue(seqUnicode); + + Sequence<OUString> seqUnicode2; + seqUnicode2 = xKey->getStringListValue(); + TEST_ENSHURE( seqUnicode2.getLength() == 3, "test_SimpleRegistry error 22" ); + TEST_ENSHURE( seqUnicode2.getArray()[0] == OUString( RTL_CONSTASCII_USTRINGPARAM("Hallo") ), "test_SimpleRegistry error 23"); + TEST_ENSHURE( seqUnicode2.getArray()[1] == OUString( RTL_CONSTASCII_USTRINGPARAM("jetzt komm") ), "test_SimpleRegistry error 24"); + TEST_ENSHURE( seqUnicode2.getArray()[2] == OUString( RTL_CONSTASCII_USTRINGPARAM("ich als unicode") ), "test_SimpleRegistry error 25"); + + + xReg->open(testreg2, sal_False, sal_True); + TEST_ENSHURE( xReg->isValid() != sal_False, "test_SimpleRegistry error 25" ); + xRootKey = xReg->getRootKey(); + xKey = xRootKey->createKey(OUString( RTL_CONSTASCII_USTRINGPARAM("ThirdKey/FirstSubKey/WithSubSubKey") )); + xKey->closeKey(); + TEST_ENSHURE( + xRootKey->createLink( + OUString( RTL_CONSTASCII_USTRINGPARAM("LinkTest") ), + OUString( RTL_CONSTASCII_USTRINGPARAM("/ThirdKey/FirstSubKey/WithSubSubKey") )), + "test_SimpleRegistry error 1212" ); + xRootKey->closeKey(); + xReg->close(); + + xReg->open(testreg, sal_False, sal_False); + TEST_ENSHURE( xReg->isValid() != sal_False, "test_SimpleRegistry error 26" ); + + if (bMergeDifferently) + { + mergeKeys( + xReg, + OUString(), + testreg2 ); + } + else + { + xReg->mergeKey(OUString(), testreg2); + } + + xRootKey = xReg->getRootKey(); + xKey = xRootKey->openKey( OUString( RTL_CONSTASCII_USTRINGPARAM("LinkTest") ) ); + TEST_ENSHURE( + xKey.is() && xKey->isValid() && + xKey->getKeyName().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("/ThirdKey/FirstSubKey/WithSubSubKey") ), + "test_SimpleRegistry error 1213" ); + xKey->closeKey(); + TEST_ENSHURE( + xRootKey->getKeyType( OUString( RTL_CONSTASCII_USTRINGPARAM("LinkTest") ) ) == + registry::RegistryKeyType_LINK, + "test_SimpleRegistry error 1214" ); + + xKey = xRootKey->openKey(OUString( RTL_CONSTASCII_USTRINGPARAM("FirstKey/SecondSubKey") )); + TEST_ENSHURE( !xKey.is(), "test_SimpleRegistry error 27" ); + + // Test Links + xKey = xRootKey->createKey(OUString( RTL_CONSTASCII_USTRINGPARAM("FifthKey") )); + xKey->createLink(OUString( RTL_CONSTASCII_USTRINGPARAM("MyFirstLink") ), + OUString( RTL_CONSTASCII_USTRINGPARAM("/ThirdKey/FirstSubKey") )); + + xKey = xRootKey->openKey(OUString( RTL_CONSTASCII_USTRINGPARAM("/FifthKey/MyFirstLink") )); + TEST_ENSHURE( xKey->isValid(), "test_SimpleRegistry error 27" ); + TEST_ENSHURE( xKey->getKeyName() == OUString( RTL_CONSTASCII_USTRINGPARAM("/ThirdKey/FirstSubKey") ), "test_SimpleRegistry error 28" ); + + xKey->createLink(OUString( RTL_CONSTASCII_USTRINGPARAM("/WithSubSubKey/MyFourthLink") ), + OUString( RTL_CONSTASCII_USTRINGPARAM("/FourthKey/MySecondLink") )); + + TEST_ENSHURE( xKey->getLinkTarget(OUString( RTL_CONSTASCII_USTRINGPARAM("/WithSubSubKey/MyFourthLink") )) + == OUString( RTL_CONSTASCII_USTRINGPARAM("/FourthKey/MySecondLink") ), "test_SimpleRegistry error 29" ); + + try + { + TEST_ENSHURE( xKey->getResolvedName(OUString( RTL_CONSTASCII_USTRINGPARAM("/WithSubSubKey/MyFourthLink/BlaBlaBla") )) + == OUString( RTL_CONSTASCII_USTRINGPARAM("/FourthKey/MySecondLink/BlaBlaBla") ), "test_SimpleRegistry error 30" ); + } + catch(InvalidRegistryException&) + { + } + + xRootKey->createLink(OUString( RTL_CONSTASCII_USTRINGPARAM("/FourthKey/MySecondLink") ), + OUString( RTL_CONSTASCII_USTRINGPARAM("/SixthKey/MyThirdLink") )); + xKey = xRootKey->createKey(OUString( RTL_CONSTASCII_USTRINGPARAM("SixthKey") )); + xKey->createLink(OUString( RTL_CONSTASCII_USTRINGPARAM("MyThirdLink") ), + OUString( RTL_CONSTASCII_USTRINGPARAM("/FourthKey/MySecondLink") )); + + xKey = xRootKey->createKey(OUString( RTL_CONSTASCII_USTRINGPARAM("/SixthKey/SixthSubKey") )); + + try + { + xRootKey->openKey(OUString( RTL_CONSTASCII_USTRINGPARAM("/FifthKey/MyFirstLink/WithSubSubKey/MyFourthLink") )); + } + catch(InvalidRegistryException&) + { + } + + TEST_ENSHURE( xRootKey->getLinkTarget(OUString( RTL_CONSTASCII_USTRINGPARAM("/FifthKey/MyFirstLink/WithSubSubKey/MyFourthLink") )) + == OUString( RTL_CONSTASCII_USTRINGPARAM("/FourthKey/MySecondLink") ), "test_SimpleRegistry error 31" ); + + xRootKey->deleteLink(OUString( RTL_CONSTASCII_USTRINGPARAM("/FifthKey/MyFirstLink/WithSubSubKey/MyFourthLink") )); + + xRootKey->createLink(OUString( RTL_CONSTASCII_USTRINGPARAM("/FourthKey/MySecondLink") ), + OUString( RTL_CONSTASCII_USTRINGPARAM("/ThirdKey/FirstSubKey/WithSubSubKey") )); + + xKey = xRootKey->openKey(OUString( RTL_CONSTASCII_USTRINGPARAM("SixthKey") )); + seqNames = xKey->getKeyNames(); + seqKeys = xKey->openKeys(); + + TEST_ENSHURE( seqNames.getArray()[0] == OUString( RTL_CONSTASCII_USTRINGPARAM("/SixthKey/SixthSubKey") ), + "test_SimpleRegistry error 32" ); + TEST_ENSHURE( seqNames.getArray()[1] == OUString( RTL_CONSTASCII_USTRINGPARAM("/SixthKey/MyThirdLink") ), + "test_SimpleRegistry error 33" ); + + TEST_ENSHURE( seqKeys.getArray()[0]->getKeyName() == OUString( RTL_CONSTASCII_USTRINGPARAM("/SixthKey/SixthSubKey") ), + "test_SimpleRegistry error 34" ); + TEST_ENSHURE( seqKeys.getArray()[1]->getKeyName() == OUString( RTL_CONSTASCII_USTRINGPARAM("/ThirdKey/FirstSubKey/WithSubSubKey") ), + "test_SimpleRegistry error 35" ); + + xRootKey->deleteLink(OUString( RTL_CONSTASCII_USTRINGPARAM("/FourthKey/MySecondLink") )); + xRootKey->closeKey(); + } + catch(InvalidRegistryException&) + { + TEST_ENSHURE(0, "exception InvalidRegistryExcption raised while doing test_SimpleRegistry"); + } + catch(InvalidValueException&) + { + TEST_ENSHURE(0, "exception InvalidValueExcption raised while doing test_SimpleRegistry()"); + } + + xReg.clear(); + + printf("Test SimpleRegistry, OK!\n"); +} + + +void test_DefaultRegistry( + OUString const & testreg, + OUString const & testreg2, + bool bMergeDifferently = false ) +{ + // Test NestedRegistry + OUString exePath( getExePath() ); + OUString userRdb(exePath); + OUString applicatRdb(exePath); + + userRdb += OUString::createFromAscii("user.rdb"); + applicatRdb += OUString::createFromAscii("stoctest.rdb"); + + Reference < XMultiServiceFactory > rSMgr = ::cppu::createRegistryServiceFactory( userRdb, applicatRdb, sal_False, OUString()); + //OUString::createFromAscii("//./e:/src596/stoc/wntmsci3/bin") ); + + Reference< XPropertySet > xPropSet( rSMgr, UNO_QUERY); + TEST_ENSHURE( xPropSet.is(), "test_DefaultRegistry error0"); + + Any aPropertyAny( xPropSet->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("Registry")) ) ); + TEST_ENSHURE( aPropertyAny.hasValue(), "test_DefaultRegistry error1"); + + Reference<XSimpleRegistry> xReg; + aPropertyAny >>= xReg; + TEST_ENSHURE( xReg.is(), "test_DefaultRegistry error1a"); + + Reference<XServiceInfo> xServInfo( Reference<XServiceInfo>::query(xReg) ); + + TEST_ENSHURE( xServInfo.is(), "test_DefaultRegistry error2"); + + TEST_ENSHURE( xServInfo->getImplementationName() == OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.stoc.NestedRegistry") ), "test_DefualtRegistry error3"); + TEST_ENSHURE( xServInfo->supportsService(OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.registry.NestedRegistry") )), "test_DefaultRegistry error4"); + TEST_ENSHURE( xServInfo->getSupportedServiceNames().getLength() == 1, "test_DefaultRegistry error5"); + xServInfo.clear(); + + TEST_ENSHURE( xReg.is(), "test_DefaultRegistry error6"); + + try + { + Reference<XRegistryKey> xRootKey(xReg->getRootKey()); + + Reference<XRegistryKey> xKey = xRootKey->openKey(OUString( RTL_CONSTASCII_USTRINGPARAM("/UCR/com/sun/star/registry/XSimpleRegistry") )); + + TEST_ENSHURE( xKey->getKeyName() == OUString( RTL_CONSTASCII_USTRINGPARAM("/UCR/com/sun/star/registry/XSimpleRegistry") ), + "test_DefaultRegistry error 7" ); + + if (bMergeDifferently) + { + mergeKeys( + xReg, + OUString( RTL_CONSTASCII_USTRINGPARAM("Test") ), + testreg ); + } + else + { + xReg->mergeKey(OUString( RTL_CONSTASCII_USTRINGPARAM("Test") ), testreg ); + } + + xKey = xRootKey->openKey(OUString( RTL_CONSTASCII_USTRINGPARAM("Test/ThirdKey/FirstSubKey/WithSubSubKey") )); + if (xKey.is()) + xKey->setLongValue(123456789); + + xKey = xRootKey->openKey(OUString( RTL_CONSTASCII_USTRINGPARAM("Test/ThirdKey/FirstSubKey") )); + if (xKey.is()) + { + xKey->createKey(OUString( RTL_CONSTASCII_USTRINGPARAM("SecondSubSubKey") )); + + Sequence<OUString> seqNames = xKey->getKeyNames(); + + TEST_ENSHURE( seqNames.getLength() == 2, "test_DefaultRegistry error 8" ); + } + + xKey = xRootKey->openKey(OUString( RTL_CONSTASCII_USTRINGPARAM("/Test/ThirdKey") )); + if (xKey.is()) + { + RegistryValueType valueType = xKey->getValueType(); + TEST_ENSHURE( valueType == RegistryValueType_ASCIILIST, "test_DefaultRegistry error 9" ); + + Sequence<OUString> seqValue = xKey->getAsciiListValue(); + + TEST_ENSHURE( seqValue.getLength() == 3, "test_DefaultRegistry error 10" ); + TEST_ENSHURE( seqValue.getArray()[0] == OUString( RTL_CONSTASCII_USTRINGPARAM("Hallo") ), + "test_DefaultRegistry error 11" ); + TEST_ENSHURE( seqValue.getArray()[1] == OUString( RTL_CONSTASCII_USTRINGPARAM("jetzt komm") ), + "test_DefaultRegistry error 12" ); + TEST_ENSHURE( seqValue.getArray()[2] == OUString( RTL_CONSTASCII_USTRINGPARAM("ich") ), + "test_DefaultRegistry error 13" ); + + Sequence<sal_Int32> seqLong(3); + seqLong.getArray()[0] = 1234; + seqLong.getArray()[1] = 4567; + seqLong.getArray()[2] = 7890; + + xKey->setLongListValue(seqLong); + + Sequence<sal_Int32> seqLongValue = xKey->getLongListValue(); + + TEST_ENSHURE( seqLongValue.getLength() == 3, "test_DefaultRegistry error 14" ); + TEST_ENSHURE( seqLongValue.getArray()[0] == 1234, "test_DefaultRegistry error 15" ); + TEST_ENSHURE( seqLongValue.getArray()[1] == 4567, "test_DefaultRegistry error 16" ); + TEST_ENSHURE( seqLongValue.getArray()[2] == 7890, "test_DefaultRegistry error 17" ); + } + + // Test Links + xKey = xRootKey->createKey(OUString( RTL_CONSTASCII_USTRINGPARAM("/Test/FifthKey") )); + xKey->createLink(OUString( RTL_CONSTASCII_USTRINGPARAM("MyFirstLink") ), + OUString( RTL_CONSTASCII_USTRINGPARAM("/Test/ThirdKey/FirstSubKey") )); + + xKey = xRootKey->openKey(OUString( RTL_CONSTASCII_USTRINGPARAM("/Test/FifthKey/MyFirstLink") )); + TEST_ENSHURE( xKey->isValid(), "test_DefaultRegistry error 18" ); + TEST_ENSHURE( xKey->getKeyName() == OUString( RTL_CONSTASCII_USTRINGPARAM("/Test/ThirdKey/FirstSubKey") ), + "test_DefaultRegistry error 19" ); + + xKey->createLink(OUString( RTL_CONSTASCII_USTRINGPARAM("/WithSubSubKey/MyFourthLink") ), + OUString( RTL_CONSTASCII_USTRINGPARAM("/Test/FourthKey/MySecondLink") )); + + TEST_ENSHURE( xKey->getLinkTarget(OUString( RTL_CONSTASCII_USTRINGPARAM("/WithSubSubKey/MyFourthLink") )) + == OUString( RTL_CONSTASCII_USTRINGPARAM("/Test/FourthKey/MySecondLink") ), + "test_DefaultRegistry error 20" ); + + try + { + TEST_ENSHURE( xKey->getResolvedName(OUString( RTL_CONSTASCII_USTRINGPARAM("/WithSubSubKey/MyFourthLink/BlaBlaBla") )) + == OUString( RTL_CONSTASCII_USTRINGPARAM("/Test/FourthKey/MySecondLink/BlaBlaBla") ), + "test_DefaultRegistry error 21" ); + } + catch(InvalidRegistryException&) + { + } + + xRootKey->createLink(OUString( RTL_CONSTASCII_USTRINGPARAM("/Test/FourthKey/MySecondLink") ), + OUString( RTL_CONSTASCII_USTRINGPARAM("/Test/SixthKey/MyThirdLink") )); + xKey = xRootKey->createKey(OUString( RTL_CONSTASCII_USTRINGPARAM("/Test/SixthKey") )); + xKey->createLink(OUString( RTL_CONSTASCII_USTRINGPARAM("MyThirdLink") ), + OUString( RTL_CONSTASCII_USTRINGPARAM("/Test/FourthKey/MySecondLink") )); + + try + { + xRootKey->openKey(OUString( RTL_CONSTASCII_USTRINGPARAM("/Test/FifthKey/MyFirstLink/WithSubSubKey/MyFourthLink") )); + } + catch(InvalidRegistryException&) + { + printf("test InvalidRegistryExcption OK!\n"); + } + + TEST_ENSHURE( xRootKey->getLinkTarget(OUString( RTL_CONSTASCII_USTRINGPARAM("/Test/FifthKey/MyFirstLink/WithSubSubKey/MyFourthLink") )) + == OUString( RTL_CONSTASCII_USTRINGPARAM("/Test/FourthKey/MySecondLink") ), + "test_DefaultRegistry error 22" ); + + xRootKey->deleteLink(OUString( RTL_CONSTASCII_USTRINGPARAM("/Test/FifthKey/MyFirstLink/WithSubSubKey/MyFourthLink") )); + + xKey = xRootKey->openKey(OUString( RTL_CONSTASCII_USTRINGPARAM("/Test/DefaultLink/SecondSubSubKey") )); + if (xKey.is()) + { + TEST_ENSHURE( xKey->getKeyName() == OUString( RTL_CONSTASCII_USTRINGPARAM("/Test/ThirdKey/FirstSubKey/SecondSubSubKey") ), "test_DefaultRegistry error 23" ); + } + xKey = xRootKey->createKey(OUString( RTL_CONSTASCII_USTRINGPARAM("/Test/DefaultLink/ThirdSubSubKey") )); + if (xKey.is()) + { + TEST_ENSHURE( xKey->getKeyName() == OUString( RTL_CONSTASCII_USTRINGPARAM("/Test/ThirdKey/FirstSubKey/ThirdSubSubKey") ), + "test_DefaultRegistry error 24" ); + } + + xKey = xRootKey->openKey(OUString( RTL_CONSTASCII_USTRINGPARAM("Test") )); + TEST_ENSHURE( xKey->isValid(), "test_DefaultRegistry error 25" ); + + xRootKey->deleteKey(OUString( RTL_CONSTASCII_USTRINGPARAM("Test") )); + + if (bMergeDifferently) + { + mergeKeys( + xReg, + OUString( RTL_CONSTASCII_USTRINGPARAM("AllFromTestreg2") ), + testreg2); + } + else + { + xReg->mergeKey(OUString( RTL_CONSTASCII_USTRINGPARAM("AllFromTestreg2") ), + testreg2); + } + + xKey = xRootKey->openKey(OUString( RTL_CONSTASCII_USTRINGPARAM("/AllFromTestreg2/ThirdKey/FirstSubKey") )); + if (xKey.is()) + { + xRootKey->deleteKey(OUString( RTL_CONSTASCII_USTRINGPARAM("/AllFromTestreg2") )); + } + + } + catch(InvalidRegistryException&) + { + TEST_ENSHURE(0, "exception InvalidRegistryExcption raised while doing test_DefaultRegistry"); + } + catch(InvalidValueException&) + { + TEST_ENSHURE(0, "exception InvalidValueExcption raised while doing test_DefaultRegistry()"); + } + try + { + xReg->close(); + } + catch(InvalidRegistryException& e) + { + (void)e; + TEST_ENSHURE(0, OUStringToOString(e.Message,RTL_TEXTENCODING_ASCII_US).getStr()); + } + + + xReg.clear(); + + // shutdown + Reference< ::com::sun::star::lang::XComponent > xComp( rSMgr, UNO_QUERY ); + OSL_ENSURE( xComp.is(), "### serivce manager has to implement XComponent!" ); + xComp->dispose(); + + printf("Test DefaultRegistry, OK!\n"); +} + + +SAL_IMPLEMENT_MAIN() +{ +// setStarUserRegistry(); + setLinkInDefaultRegistry(OUString::createFromAscii("/Test/DefaultLink"), + OUString::createFromAscii("/Test/FifthKey/MyFirstLink")); + + OUString reg1( RTL_CONSTASCII_USTRINGPARAM("testreg1.rdb") ); + OUString reg2( RTL_CONSTASCII_USTRINGPARAM("testreg2.rdb") ); + OUString areg1( RTL_CONSTASCII_USTRINGPARAM("atestreg1.rdb") ); + OUString areg2( RTL_CONSTASCII_USTRINGPARAM("atestreg2.rdb") ); + + test_SimpleRegistry( reg1, reg2 ); + test_DefaultRegistry( reg1, reg2 ); + test_SimpleRegistry( areg1, areg2, true ); // use different merge + test_DefaultRegistry( areg1, areg2, true ); + + Reference< XSimpleRegistry > xSimReg( ::cppu::createSimpleRegistry() ); + xSimReg->open( reg1, sal_False, sal_True ); + xSimReg->destroy(); + xSimReg->open( reg2, sal_False, sal_True ); + xSimReg->destroy(); + xSimReg->open( areg1, sal_False, sal_True ); + xSimReg->destroy(); + xSimReg->open( areg2, sal_False, sal_True ); + xSimReg->destroy(); + return(0); +} + + diff --git a/stoc/test/testsmgr.cxx b/stoc/test/testsmgr.cxx new file mode 100644 index 000000000000..afa1291db8e3 --- /dev/null +++ b/stoc/test/testsmgr.cxx @@ -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. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_stoc.hxx" +#include <stdio.h> + +#include <sal/main.h> +#include <osl/process.h> +#include <registry/registry.hxx> +#include <uno/mapping.hxx> + +#include <com/sun/star/registry/XSimpleRegistry.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> + +extern "C" void SAL_CALL test_ServiceManager(); + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#if OSL_DEBUG_LEVEL > 0 +#define TEST_ENSHURE(c, m) OSL_ENSURE(c, m) +#else +#define TEST_ENSHURE(c, m) OSL_VERIFY(c) +#endif + + +using namespace ::rtl; +OString userRegEnv("STAR_USER_REGISTRY="); + +OUString getExePath() +{ + OUString exe; + + OSL_VERIFY( osl_getExecutableFile( &exe.pData) == osl_Process_E_None); + +#if defined(WIN32) || defined(__OS2__) || defined(WNT) + exe = exe.copy(0, exe.getLength() - 16); +#else + exe = exe.copy(0, exe.getLength() - 12); +#endif + return exe; +} + +void setStarUserRegistry() +{ + Registry *myRegistry = new Registry(); + + RegistryKey rootKey, rKey, rKey2; + + OUString userReg = getExePath(); + userReg += OUString::createFromAscii("user.rdb"); + if(myRegistry->open(userReg, REG_READWRITE)) + { + TEST_ENSHURE(!myRegistry->create(userReg), "setStarUserRegistry error 1"); + } + + TEST_ENSHURE(!myRegistry->close(), "setStarUserRegistry error 9"); + delete myRegistry; + + userRegEnv += OUStringToOString(userReg, RTL_TEXTENCODING_ASCII_US); + putenv((char *)userRegEnv.getStr()); +} + + +SAL_IMPLEMENT_MAIN() +{ + printf( "ServiceManagerTest : \r"); + setStarUserRegistry(); + fflush( stdout ); + test_ServiceManager(); + + printf( "ServiceManagerTest : OK\n" ); + return 0; +} diff --git a/stoc/test/testsmgr2.cxx b/stoc/test/testsmgr2.cxx new file mode 100644 index 000000000000..b04f188c10f9 --- /dev/null +++ b/stoc/test/testsmgr2.cxx @@ -0,0 +1,118 @@ +/************************************************************************* + * + * 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 <stdio.h> + +#include <sal/main.h> +#include <cppuhelper/bootstrap.hxx> + +#include <com/sun/star/container/XContentEnumerationAccess.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/registry/XSimpleRegistry.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> + +using namespace ::rtl; +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::registry; + +SAL_IMPLEMENT_MAIN() +{ + try + { + + Reference< XSimpleRegistry > r1 = createSimpleRegistry(); + Reference< XSimpleRegistry > r2 = createSimpleRegistry(); + r1->open( OUString( RTL_CONSTASCII_USTRINGPARAM( "test1.rdb" ) ), sal_True, sal_False ); + r2->open( OUString( RTL_CONSTASCII_USTRINGPARAM( "test2.rdb" ) ), sal_True, sal_False ); + Reference< XSimpleRegistry > r = createNestedRegistry( ); + Reference< XInitialization > rInit( r, UNO_QUERY ); + Sequence< Any > seq( 2 ); + seq[0] <<= r1; + seq[1] <<= r2; + rInit->initialize( seq ); + + Reference< XComponentContext > rComp = bootstrap_InitialComponentContext( r ); + + Reference< XContentEnumerationAccess > xCtAccess( rComp->getServiceManager(), UNO_QUERY ); + + Reference< XEnumeration > rEnum = + xCtAccess->createContentEnumeration( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.bridge.Bridge" ) ) ); + + sal_Int32 n = 0; + while( rEnum->hasMoreElements() ) + { + Reference< XServiceInfo > r3; + rEnum->nextElement() >>= r3; + OString o = OUStringToOString( r3->getImplementationName() , RTL_TEXTENCODING_ASCII_US ); + printf( "%s\n" , o.getStr() ); + Sequence< OUString > seq2 = r3->getSupportedServiceNames(); + for( int i = 0 ;i < seq2.getLength() ; i ++ ) + { + o = OUStringToOString( seq2[i] , RTL_TEXTENCODING_ASCII_US ); + printf( " %s\n" , o.getStr() ); + } + n ++; + } + // there are two services in two registries ! + OSL_ASSERT( 2 == n ); + if( 2 == n ) + { + printf( "test passed\n" ); + } + + Reference< XComponent > xComp( rComp, UNO_QUERY ); + xComp->dispose(); + try + { + xCtAccess->createContentEnumeration( + OUString( RTL_CONSTASCII_USTRINGPARAM( "blabla" ) ) ); + } + catch (DisposedException &) + { + printf( "already disposed results in DisposedException: ok.\n" ); + return 0; + } + fprintf( stderr, "missing DisposedException!\n" ); + return 1; + } + catch ( Exception & e ) + { + OString o = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US ); + printf( "%s\n" , o.getStr() ); + OSL_ASSERT( 0 ); + return 1; + } +} diff --git a/stoc/test/testsmgr_cpnt.cxx b/stoc/test/testsmgr_cpnt.cxx new file mode 100644 index 000000000000..aecdbc55514f --- /dev/null +++ b/stoc/test/testsmgr_cpnt.cxx @@ -0,0 +1,472 @@ +/************************************************************************* + * + * 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/alloc.h> +#include <osl/security.h> +#include <osl/thread.h> +#include <osl/mutex.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/weak.hxx> +#include <uno/mapping.hxx> + + +#include <cppuhelper/factory.hxx> +#include <cppuhelper/servicefactory.hxx> +#include <cppuhelper/implbase1.hxx> +#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/registry/XImplementationRegistration.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/container/XContentEnumerationAccess.hpp> +#include <com/sun/star/container/XEnumerationAccess.hpp> +#include <com/sun/star/container/XEnumeration.hpp> + +#if defined ( UNX ) +#include <limits.h> +#define _MAX_PATH PATH_MAX +#endif + + + +#if OSL_DEBUG_LEVEL > 0 +#define TEST_ENSHURE(c, m) OSL_ENSURE(c, m) +#else +#define TEST_ENSHURE(c, m) OSL_VERIFY(c) +#endif + + +#define IMPLEMENTATION_NAME "com.sun.star.DummyService.V10" +#define SERVICE_NAME "com.sun.star.ts.TestManagerImpl" + + +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 osl; +using namespace rtl; +using namespace cppu; + + +Reference<XMultiServiceFactory> getProcessServiceManager() +{ + Reference<XMultiServiceFactory > s_x; + if (! s_x.is()) + { + MutexGuard aGuard( Mutex::getGlobalMutex() ); + if (! s_x.is()) + s_x = createRegistryServiceFactory( OUString::createFromAscii( "stoctest.rdb" ), sal_False ); + } + return s_x; +} + +Reference< XMultiServiceFactory > createRegistryServiceManager( const OUString& registryName ) +{ + return createRegistryServiceFactory( registryName ); +} + + +/********************************** +* The service, that is used to test the Service manager +* +* +* +*************************************/ +static sal_uInt32 nInstanceCount = 0; +class Test_Manager_Impl : public WeakImplHelper1< XServiceInfo > +{ +public: + Test_Manager_Impl(){ nInstanceCount++;} + ~Test_Manager_Impl(); + + // XServiceInfo + OUString SAL_CALL getImplementationName() throw(); + sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw(); + Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw(); + static Sequence< OUString > SAL_CALL getSupportedServiceNames_Static(void) throw(); + +private: +// static XIdlClassRef getStaticIdlClass(); +}; + +Test_Manager_Impl::~Test_Manager_Impl() +{ + nInstanceCount--; +} + + +// alt, wird von der neuen Mimic nicht mehr gebraucht +Reference< XInterface > SAL_CALL Test_Manager_Impl_CreateInstance_Impl() +{ + return (OWeakObject *)new Test_Manager_Impl(); +} + + +//************************************************************************* +// Test_Manager_Impl_CreateInstance() +// +Reference < XInterface > SAL_CALL Test_Manager_Impl_CreateInstance( + const Reference< XMultiServiceFactory > & /*rSMgr*/ ) throw (Exception) +{ + Reference < XInterface > xService = (XWeak *)(OWeakObject *)new Test_Manager_Impl( ); + + return xService; +} + + +//************************************************************************* +// Test_Manager_Impl::getImplementationName +// +OUString Test_Manager_Impl::getImplementationName() throw() +{ + return OUString::createFromAscii(IMPLEMENTATION_NAME); +} + +//************************************************************************* +// Test_Manager_Impl::supportsService +// +sal_Bool Test_Manager_Impl::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; +} + +//************************************************************************* +// Test_Manager_Impl::getSupportedServiceNames +// +Sequence< OUString > Test_Manager_Impl::getSupportedServiceNames(void) throw () +{ + return getSupportedServiceNames_Static(); +} + +//************************************************************************* +// Test_Manager_Impl::getSupportedServiceNames_Static +// +Sequence< OUString > Test_Manager_Impl::getSupportedServiceNames_Static(void) throw () +{ + Sequence< OUString > aSNS( 2 ); + aSNS.getArray()[0] = OUString::createFromAscii(SERVICE_NAME); + aSNS.getArray()[1] = OUString::createFromAscii("com.sun.star.bridge.Bridge"); + return aSNS; +} + + + + +/**** +* +* +* This routine performs the test of the process service manager ( getProcessServiceManager is called ) +* +* +* +****/ + +#include <stdio.h> + +extern "C" void SAL_CALL test_ServiceManager() +{ +#if ! defined SAL_DLLPREFIX +#define SAL_DLLPREFIX "" +#endif + OUString atUModule2 = OUString( + RTL_CONSTASCII_USTRINGPARAM( + SAL_DLLPREFIX "testsmgr_component" SAL_DLLEXTENSION ) ); + + // expand shared library name + OString atModule2( OUStringToOString(atUModule2, RTL_TEXTENCODING_ASCII_US) ); + + // get the process servicemanager + Reference <XMultiServiceFactory> xSMgr = getProcessServiceManager(); + + TEST_ENSHURE( xSMgr.is() , "query on XServiceManager failed" ); + + Reference<XContentEnumerationAccess> xContEnum(xSMgr, UNO_QUERY); + TEST_ENSHURE( xContEnum.is() , "query on XContentEnumerationAccess failed" ); + Reference<XEnumeration > xEnum(xContEnum->createContentEnumeration(OUString::createFromAscii("com.sun.star.registry.SimpleRegistry"))); + TEST_ENSHURE( xEnum.is() , "createContentEnumeration failed" ); + sal_Int32 nLen = 0; + while( xEnum->hasMoreElements() ) + { + nLen++; + xEnum->nextElement(); + } + TEST_ENSHURE( nLen == 1, "more than one implementation for SimpleRegistry" ); + + Reference<XEnumerationAccess> xImplEnum(xSMgr, UNO_QUERY); + TEST_ENSHURE( xImplEnum.is() , "query on XEnumeration failed" ); + xEnum = Reference<XEnumeration >(xImplEnum->createEnumeration()); + TEST_ENSHURE( xEnum.is() , "createEnumeration failed" ); + nLen = 0; + while( xEnum->hasMoreElements() ) + { + nLen++; + Reference< XServiceInfo > sf( xEnum->nextElement(), UNO_QUERY ); + OString str( OUStringToOString( sf->getImplementationName(), RTL_TEXTENCODING_ASCII_US ) ); + ::fprintf( stderr, "> implementation name: %s\n", str.getStr() ); + } + TEST_ENSHURE( nLen == 8, "more than 6 factories" ); + + // try to get an instance for a unknown service + TEST_ENSHURE( !xSMgr->createInstance(OUString::createFromAscii("bla.blup.Q")).is(), "unknown service provider found" ); + + // + // First test : register service via the internal function of the component itself + // + { + Reference< XImplementationRegistration > + xInst( xSMgr->createInstance(OUString::createFromAscii("com.sun.star.registry.ImplementationRegistration")), UNO_QUERY ); + TEST_ENSHURE( xInst.is(), "no ImplementationRegistration" ); + + try { + // register the services via writeComponentRegInfo (see at end of this file) + xInst->registerImplementation(OUString::createFromAscii("com.sun.star.loader.SharedLibrary"), atUModule2, Reference< XSimpleRegistry >() ); + } + catch( CannotRegisterImplementationException e ) { + TEST_ENSHURE( 0, "register implementation failed" ); + } + + // getImplementations() check + Sequence<OUString> seqImpl = xInst->getImplementations(OUString::createFromAscii("com.sun.star.loader.SharedLibrary"), atUModule2); + TEST_ENSHURE( seqImpl.getLength() == 1, "count of implementantions is wrong" ); + TEST_ENSHURE( seqImpl.getConstArray()[0] == OUString::createFromAscii("com.sun.star.DummyService.V10"), "implementation name is not equal" ); + + + // tests, if a service provider can be instantiated. + + Reference< XInterface > xIFace(xSMgr->createInstance(OUString::createFromAscii("com.sun.star.ts.TestManagerImpl"))); + TEST_ENSHURE( xIFace.is(), "loadable service not found" ); + + // remove the service + TEST_ENSHURE( xInst->revokeImplementation(atUModule2, Reference< XSimpleRegistry > ()), + "revoke implementation failed" ); + } + + +// Reference < XSimpleRegistry > xSReg( xSMgr->createInstance(OUString::createFromAscii("com::sun::star.uno.repos.SimpleRegistry")), UNO_QUERY ); +// TEST_ENSHURE( xSReg.is() , "Simple registry couldn't be instantiated" ); + +// xSReg->open(OUString::createFromAscii("dummy.reg"), sal_False, sal_True); +// xSReg->close(); + + // laut dbo : C-API muss nicht mehr unterstuezt werden + //TEST_ENSHURE( registerExternService(atModule, "dummy.reg"), "install failed" ); + //TEST_ENSHURE( deregisterExternService(atModule, "dummy.reg"), "deinstall failed" ); + + +// UNO_INTERFACE(XMultiServiceFactory) xUnoSMgr = {0,0}; +// smart2uno(xSMgr, xUnoSMgr); + +// TEST_ENSHURE(registerExternImplementation(xUnoSMgr, "com::sun::star.loader.SharedLibrary", atModule2, "dummy.reg"), "install failed" ); +// TEST_ENSHURE(revokeExternImplementation(xUnoSMgr, atModule2, "dummy.reg"), "deinstall failed" ); + +// TEST_ENSHURE(registerExternImplementation(xUnoSMgr, "com::sun::star.loader.SharedLibrary", atModule2, "dummy2.reg"), "install failed" ); + +//TODO : Java loader test +// String testUrl(getTestJarUrl()); +// TEST_ENSHURE(registerExternImplementation(xUnoSMgr, "com::sun::star.loader.Java", testUrl, "dummy.reg"), "install failed" ); +// TEST_ENSHURE(revokeExternImplementation(xUnoSMgr, testUrl, "dummy.reg"), "deinstall failed" ); + +// if (!UNO_isNull((UNO_Ifc*)&xUnoSMgr)) +// xUnoSMgr.m_pVmt->release(xUnoSMgr.m_pCtx); + +// xSReg->open(OUString::createFromAscii("dummy.reg"), sal_True, sal_False); +// TEST_ENSHURE(!xSReg->getRootKey()->openKey(OUString::createFromAscii("/SERVICES/com::sun::star/ts/TestManagerImpl/URL")).is(), +// "deinstall failed" ); + +// xSReg->close(); + +// xSReg->open(OUString::createFromAscii("dummy.reg"), sal_False, sal_False); +// xSReg->destroy(); +// xSReg->open(OUString::createFromAscii("dummy2.reg"), sal_False, sal_False); +// xSReg->destroy(); + + + // Test initialisieren +/* + XServiceProviderRef xSiSP1 = createSimpleServiceProvider( OUString::createFromAscii("com::sun::star.usr.Test_Manager_Impl1"), Test_Manager_Impl_getReflection ); + XServiceProviderRef xSiSP11 = createSimpleServiceProvider( OUString::createFromAscii("com::sun::star.usr.Test_Manager_Impl1"), Test_Manager_Impl_getReflection ); + XServiceProviderRef xSiSP2 = createSimpleServiceProvider( OUString::createFromAscii("com::sun::star.usr.Test_Manager_Impl2"), Test_Manager_Impl_getReflection ); +*/ +/* + // second test + // create XServiceProvider via createSingleFactory and write them directly into the registry + // For this is needed a sequence of supported servicenames and a createComponent function pointer + { + Reference< XServiceProvider > xSiSP1(createSingleFactory( + xSMgr, + OUString::createFromAscii("com::sun::star.usr.Test_Manager_Impl1), + Test_Manager_Impl_CreateInstance, + Test_Manager_Impl::getSupportedServiceNames_Static() ), UNO_QUERY); + Reference< XServiceProvider > xSiSP11(createSingleFactory( + xSMgr, + OUString::createFromAscii("com::sun::star.usr.Test_Manager_Impl1"), + Test_Manager_Impl_CreateInstance, + Test_Manager_Impl::getSupportedServiceNames_Static() ),UNO_QUERY); + Reference< XServiceProvider > xSiSP2(createSingleFactory( + xSMgr, + L"com::sun::star.usr.Test_Manager_Impl2", + Test_Manager_Impl_CreateInstance, + Test_Manager_Impl::getSupportedServiceNames_Static() ), UNO_QUERY); + + // put the service providers into the registry + xReg->registerServiceProvider( L"com::sun::star.test.TestManager1", xSiSP1 ); + xReg->registerServiceProvider( L"com::sun::star.test.TestManager1", xSiSP11 ); + xReg->registerServiceProvider( L"com::sun::star.test.TestManager2", xSiSP2 ); + + // TestManager1 + Reference< XServiceProvider > xProv = xSMgr->queryServiceProvider( L"com::sun::star.test.TestManager1"); + Reference< XSingleServiceFactory > xFact( xProv, UNO_QUERY ); + TEST_ENSHURE( xFact.is(), "Service com::sun::star.test.TestManager1 not found" ); + + Reference< XInterface > xTest1 = xFact->createInstance(); + TEST_ENSHURE( nInstanceCount == 1, "wrong service instanciated" ); + + // TestManager2 + xProv = xSMgr->queryServiceProvider( L"com::sun::star.test.TestManager2"); + xFact = Reference < XSingleServiceFactory > ( xProv , UNO_QUERY ); + TEST_ENSHURE( xFact.is(), "Service com::sun::star.test.TestManager2 not found" ); + + Reference < XInterface > xTest2 = xFact->createInstance(); + TEST_ENSHURE( nInstanceCount == 2, "wrong service instanciated" ); + + xTest1 = Reference< XInterface >(); + xTest2 = Reference< XInterface >(); + TEST_ENSHURE( nInstanceCount == 0, "wrong service deleted" ); + + Reference< XEnumeration > xEnum = xSMgr->createProviderEnumeration( L"com::sun::star.test.TestManager1"); + TEST_ENSHURE( xEnum.is() , "no provider enumeration" ); + + sal_Int32 nSPTestManagerImplLen2 = 0; + + while (xEnum.is() && xEnum->hasMoreElements()) + { + nSPTestManagerImplLen2++; + xEnum->nextElement(); + + } + TEST_ENSHURE( nSPTestManagerImplLen2 == 2, "queryServiceProviders() wrong length" ); + + sal_Int32 nCount = 0; + xEnum = xSMgr->createProviderEnumeration( L"com::sun::star.test.TestManager1"); + while (xEnum->hasMoreElements()) + { + Reference< XServiceProvider > xProv; + xEnum->nextElement() >>= xProv; + if (xProv == xSiSP1 || xProv == xSiSP11) + nCount++; + } + + TEST_ENSHURE( nCount == 2 , "not all com::sun::star.testimpl.TestManagerImpl registered" ); +*/ +/* + { + Reference< XMultiServiceFactory > xTestManager(createRegistryServiceManager(L"testmanager.rdb")); + TEST_ENSHURE( xTestManager.is(), "create Test ServiceManager failed!" ); + } +*/ + Reference<XComponent> xComp(xSMgr, UNO_QUERY); + xComp->dispose(); + + xComp.clear(); + xSMgr.clear(); +} + + + +extern "C" +{ +//================================================================================================== +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /*ppEnv*/ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} +//================================================================================================== +sal_Bool SAL_CALL component_writeInfo( + void * /*pServiceManager*/, void * pRegistryKey ) +{ + if (pRegistryKey) + { + try + { + Reference< XRegistryKey > xNewKey( + reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey( + OUString( RTL_CONSTASCII_USTRINGPARAM("/" IMPLEMENTATION_NAME "/UNO/SERVICES") ) ) ); + + const Sequence< OUString > & rSNL = + Test_Manager_Impl::getSupportedServiceNames_Static(); + const OUString * pArray = rSNL.getConstArray(); + for ( sal_Int32 nPos = rSNL.getLength(); nPos--; ) + xNewKey->createKey( pArray[nPos] ); + + return sal_True; + } + catch (InvalidRegistryException &) + { + OSL_ENSURE( sal_False, "### InvalidRegistryException!" ); + } + } + return sal_False; +} +//================================================================================================== +void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ ) +{ + void * pRet = 0; + + if (rtl_str_compare( pImplName, IMPLEMENTATION_NAME ) == 0) + { + Reference< XSingleServiceFactory > xFactory( createSingleFactory( + reinterpret_cast< XMultiServiceFactory * >( pServiceManager ), + OUString( RTL_CONSTASCII_USTRINGPARAM(IMPLEMENTATION_NAME) ), + Test_Manager_Impl_CreateInstance, + Test_Manager_Impl::getSupportedServiceNames_Static() ) ); + + if (xFactory.is()) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } + + return pRet; +} +} + + + diff --git a/stoc/test/testsmgr_cpnt.map b/stoc/test/testsmgr_cpnt.map new file mode 100644 index 000000000000..ab5ed357b461 --- /dev/null +++ b/stoc/test/testsmgr_cpnt.map @@ -0,0 +1,9 @@ +UDK_3_0_0 { + global: + component_getImplementationEnvironment; + component_writeInfo; + component_getFactory; + test_ServiceManager; + local: + *; +}; diff --git a/stoc/test/uriproc/makefile.mk b/stoc/test/uriproc/makefile.mk new file mode 100644 index 000000000000..cfdc33e7586b --- /dev/null +++ b/stoc/test/uriproc/makefile.mk @@ -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 "$(OOO_SUBSEQUENT_TESTS)" == "" +nothing .PHONY: +.ELSE + +PRJ := ../.. +PRJNAME := stoc +TARGET := test_uriproc + +ENABLE_EXCEPTIONS := TRUE + +.INCLUDE: settings.mk + +CFLAGSCXX += $(CPPUNIT_CFLAGS) +DLLPRE = # no leading "lib" on .so files + +SHL1TARGET = $(TARGET) +SHL1OBJS = $(SLO)/test_uriproc.obj +SHL1STDLIBS = $(CPPULIB) $(CPPUHELPERLIB) $(CPPUNITLIB) $(SALLIB) +SHL1VERSIONMAP = version.map +SHL1RPATH = NONE +SHL1IMPLIB = i$(SHL1TARGET) +DEF1NAME = $(SHL1TARGET) + +SLOFILES = $(SHL1OBJS) + +.INCLUDE: target.mk + +.IF "$(OS)" == "WNT" +my_file = file:/// +.ELSE +my_file = file:// +.END + +ALLTAR: test + +test .PHONY: $(SHL1TARGETN) $(MISC)/$(TARGET)/services.rdb + $(CPPUNITTESTER) $(SHL1TARGETN) \ + -env:UNO_SERVICES=$(my_file)$(PWD)/$(MISC)/$(TARGET)/services.rdb \ + -env:UNO_TYPES=$(my_file)$(SOLARBINDIR)/udkapi.rdb \ + -env:OOO_TEST_PREFIX=$(my_file)$(PWD)/$(DLLDEST)/ + +$(MISC)/$(TARGET)/services.rdb: + $(MKDIRHIER) $(@:d) + $(RM) $@ + $(REGCOMP) -register -r $@ -wop=vnd.sun.star.expand:\$${{OOO_TEST_PREFIX}} \ + -c $(DLLDEST)/stocservices.uno$(DLLPOST) + +.END diff --git a/stoc/test/uriproc/test_uriproc.cxx b/stoc/test/uriproc/test_uriproc.cxx new file mode 100644 index 000000000000..a7ad8d9abf94 --- /dev/null +++ b/stoc/test/uriproc/test_uriproc.cxx @@ -0,0 +1,1004 @@ +/************************************************************************* + * + * 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 "com/sun/star/lang/XComponent.hpp" +#include "com/sun/star/lang/XMultiComponentFactory.hpp" +#include "com/sun/star/uno/Reference.hxx" +#include "com/sun/star/uno/XComponentContext.hpp" +#include "com/sun/star/uri/ExternalUriReferenceTranslator.hpp" +#include "com/sun/star/uri/UriReferenceFactory.hpp" +#include "com/sun/star/uri/VndSunStarPkgUrlReferenceFactory.hpp" +#include "com/sun/star/uri/XExternalUriReferenceTranslator.hpp" +#include "com/sun/star/uri/XUriReference.hpp" +#include "com/sun/star/uri/XUriReferenceFactory.hpp" +#include "com/sun/star/uri/XVndSunStarExpandUrlReference.hpp" +#include "com/sun/star/uri/XVndSunStarPkgUrlReferenceFactory.hpp" +#include "com/sun/star/uri/XVndSunStarScriptUrlReference.hpp" +#include "com/sun/star/util/XMacroExpander.hpp" +#include "cppuhelper/bootstrap.hxx" +#include "cppunit/TestAssert.h" +#include "cppunit/TestFixture.h" +#include "cppunit/extensions/HelperMacros.h" +#include "cppunit/plugin/TestPlugIn.h" +#include "osl/diagnose.h" +#include "rtl/string.h" +#include "rtl/string.hxx" +#include "rtl/textenc.h" +#include "rtl/ustrbuf.hxx" +#include "rtl/ustring.hxx" +#include "sal/types.h" + +#include <cstdlib> + +namespace css = com::sun::star; + +namespace { + +#define TEST_ASSERT_EQUAL(token1, token2, token3, expected, actual) \ + CPPUNIT_ASSERT_MESSAGE( \ + createTestAssertEqualMessage( \ + token1, token2, token3, #expected, #actual, expected, actual). \ + getStr(), \ + (actual) == (expected)) + +template< typename T > void append( + rtl::OUStringBuffer & buffer, T const & value) +{ + buffer.append(value); +} + +template<> void append(rtl::OUStringBuffer & buffer, bool const & value) { + buffer.append(static_cast< sal_Bool >(value)); +} + +template<> void append(rtl::OUStringBuffer & buffer, std::size_t const & value) +{ + buffer.append(static_cast< sal_Int32 >(value)); +} + +template<> void append(rtl::OUStringBuffer & buffer, char const * const & value) +{ + buffer.appendAscii(value); +} + +template< typename T1, typename T2, typename T3, typename T4 > +rtl::OString createTestAssertEqualMessage( + char const * token1, T1 const & token2, T2 const & token3, + char const * expectedExpr, char const * actualExpr, T3 const & expected, + T4 const & actual) +{ + rtl::OUStringBuffer buf; + buf.appendAscii(token1); + buf.append(static_cast< sal_Unicode >('|')); + append(buf, token2); + buf.append(static_cast< sal_Unicode >('|')); + append(buf, token3); + buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(": TEST_ASSERT_EQUAL(")); + buf.appendAscii(expectedExpr); + buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(", ")); + buf.appendAscii(actualExpr); + buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("): <")); + append(buf, expected); + buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("> != <")); + append(buf, actual); + buf.append(static_cast< sal_Unicode >('>')); + return rtl::OUStringToOString( + buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US); +} + +class Test: public CppUnit::TestFixture { +public: + virtual void setUp(); + + virtual void tearDown(); + + void testParse(); + + void testMakeAbsolute(); + + void testMakeRelative(); + + void testVndSunStarExpand(); + + void testVndSunStarScript(); + + void testTranslator(); + + void testPkgUrlFactory(); + + CPPUNIT_TEST_SUITE(Test); + CPPUNIT_TEST(testParse); + CPPUNIT_TEST(testMakeAbsolute); + CPPUNIT_TEST(testMakeRelative); + CPPUNIT_TEST(testVndSunStarExpand); + CPPUNIT_TEST(testVndSunStarScript); + CPPUNIT_TEST(testTranslator); + CPPUNIT_TEST(testPkgUrlFactory); + CPPUNIT_TEST_SUITE_END(); + +private: + css::uno::Reference< css::uno::XComponentContext > m_context; + css::uno::Reference< css::uri::XUriReferenceFactory > m_uriFactory; +}; + +void Test::setUp() { + m_context = cppu::defaultBootstrap_InitialComponentContext(); + m_uriFactory = css::uri::UriReferenceFactory::create(m_context); +} + +void Test::tearDown() { + m_uriFactory.clear(); + css::uno::Reference< css::lang::XComponent >( + m_context, css::uno::UNO_QUERY_THROW)->dispose(); +} + +void Test::testParse() { + struct Data { + char const * uriReference; + char const * scheme; + char const * schemeSpecificPart; + bool isHierarchical; + char const * authority; + char const * path; + bool hasRelativePath; + sal_Int32 pathSegmentCount; + char const * pathSegment0; + char const * pathSegment1; + char const * pathSegment2; + char const * pathSegment3; + char const * pathSegment4; + char const * query; + char const * fragment; + }; + Data data[] = { + { "", 0, "", true, 0, + "", true, 0, "", "", "", "", "", 0, 0 }, + { "scheme:", 0, 0, false, 0, + 0, false, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "scheme:/", "scheme", "/", true, 0, + "/", false, 1, "", "", "", "", "", 0, 0 }, + { "scheme://", "scheme", "//", true, "", + "", false, 0, "", "", "", "", "", 0, 0 }, + { "scheme:///", "scheme", "///", true, "", + "/", false, 1, "", "", "", "", "", 0, 0 }, + { "scheme:////", "scheme", "////", true, "", + "//", false, 2, "", "", "", "", "", 0, 0 }, + { "scheme:////", "scheme", "////", true, "", + "//", false, 2, "", "", "", "", "", 0, 0 }, + { "scheme:#", 0, 0, false, 0, + 0, false, 0, 0, 0, 0, 0, 0, 0, 0 }, + { "scheme:?", "scheme", "?", false, 0, + "?", false, 0, "", "", "", "", "", 0, 0 }, + { "/", 0, "/", true, 0, + "/", false, 1, "", "", "", "", "", 0, 0 }, + { "//", 0, "//", true, "", + "", false, 0, "", "", "", "", "", 0, 0 }, + { "///", 0, "///", true, "", + "/", false, 1, "", "", "", "", "", 0, 0 }, + { "////", 0, "////", true, "", + "//", false, 2, "", "", "", "", "", 0, 0 } }; + for (std::size_t i = 0; i < sizeof data / sizeof data[0]; ++i) { + css::uno::Reference< css::uri::XUriReference > uriRef( + m_uriFactory->parse( + rtl::OUString::createFromAscii(data[i].uriReference))); + CPPUNIT_ASSERT(uriRef.is() == (data[i].schemeSpecificPart != 0)); + if (uriRef.is()) { + TEST_ASSERT_EQUAL( + "testParse", i, data[i].uriReference, + rtl::OUString::createFromAscii(data[i].uriReference), + uriRef->getUriReference()); + TEST_ASSERT_EQUAL( + "testParse", i, data[i].uriReference, + data[i].scheme != 0, uriRef->isAbsolute()); + TEST_ASSERT_EQUAL( + "testParse", i, data[i].uriReference, + rtl::OUString::createFromAscii( + data[i].scheme == 0 ? "" : data[i].scheme), + uriRef->getScheme()); + TEST_ASSERT_EQUAL( + "testParse", i, data[i].uriReference, + rtl::OUString::createFromAscii(data[i].schemeSpecificPart), + uriRef->getSchemeSpecificPart()); + TEST_ASSERT_EQUAL( + "testParse", i, data[i].uriReference, + data[i].isHierarchical, + static_cast< bool >(uriRef->isHierarchical())); + TEST_ASSERT_EQUAL( + "testParse", i, data[i].uriReference, + data[i].authority != 0, uriRef->hasAuthority()); + TEST_ASSERT_EQUAL( + "testParse", i, data[i].uriReference, + rtl::OUString::createFromAscii( + data[i].authority == 0 ? "" : data[i].authority), + uriRef->getAuthority()); + TEST_ASSERT_EQUAL( + "testParse", i, data[i].uriReference, + rtl::OUString::createFromAscii(data[i].path), + uriRef->getPath()); + TEST_ASSERT_EQUAL( + "testParse", i, data[i].uriReference, + data[i].hasRelativePath, + static_cast< bool >(uriRef->hasRelativePath())); + TEST_ASSERT_EQUAL( + "testParse", i, data[i].uriReference, + data[i].pathSegmentCount, uriRef->getPathSegmentCount()); + TEST_ASSERT_EQUAL( + "testParse", i, data[i].uriReference, + rtl::OUString::createFromAscii(""), uriRef->getPathSegment(-1)); + TEST_ASSERT_EQUAL( + "testParse", i, data[i].uriReference, + rtl::OUString::createFromAscii(data[i].pathSegment0), + uriRef->getPathSegment(0)); + TEST_ASSERT_EQUAL( + "testParse", i, data[i].uriReference, + rtl::OUString::createFromAscii(data[i].pathSegment1), + uriRef->getPathSegment(1)); + TEST_ASSERT_EQUAL( + "testParse", i, data[i].uriReference, + rtl::OUString::createFromAscii(data[i].pathSegment2), + uriRef->getPathSegment(2)); + TEST_ASSERT_EQUAL( + "testParse", i, data[i].uriReference, + rtl::OUString::createFromAscii(data[i].pathSegment3), + uriRef->getPathSegment(3)); + TEST_ASSERT_EQUAL( + "testParse", i, data[i].uriReference, + rtl::OUString::createFromAscii(data[i].pathSegment4), + uriRef->getPathSegment(4)); + TEST_ASSERT_EQUAL( + "testParse", i, data[i].uriReference, + rtl::OUString::createFromAscii(""), uriRef->getPathSegment(5)); + TEST_ASSERT_EQUAL( + "testParse", i, data[i].uriReference, + data[i].query != 0, uriRef->hasQuery()); + TEST_ASSERT_EQUAL( + "testParse", i, data[i].uriReference, + rtl::OUString::createFromAscii( + data[i].query == 0 ? "" : data[i].query), + uriRef->getQuery()); + TEST_ASSERT_EQUAL( + "testParse", i, data[i].uriReference, + data[i].fragment != 0, uriRef->hasFragment()); + TEST_ASSERT_EQUAL( + "testParse", i, data[i].uriReference, + rtl::OUString::createFromAscii( + data[i].fragment == 0 ? "" : data[i].fragment), + uriRef->getFragment()); + } + } +} + +void Test::testMakeAbsolute() { + struct Data { + char const * baseUriReference; + char const * uriReference; + bool processSpecialBaseSegments; + css::uri::RelativeUriExcessParentSegments excessParentSegments; + char const * absolute; + }; + Data data[] = { + // The following tests are taken from RFC 2396, Appendix C: + { "http://a/b/c/d;p?q", "g:h", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "g:h" }, + { "http://a/b/c/d;p?q", "g", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://a/b/c/g" }, + { "http://a/b/c/d;p?q", "./g", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://a/b/c/g" }, + { "http://a/b/c/d;p?q", "g/", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://a/b/c/g/" }, + { "http://a/b/c/d;p?q", "//g", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://g" }, + { "http://a/b/c/d;p?q", "?y", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://a/b/c/?y" }, + { "http://a/b/c/d;p?q", "g?y", true, + css::uri::RelativeUriExcessParentSegments_ERROR, + "http://a/b/c/g?y" }, + { "http://a/b/c/d;p?q", "#s", true, + css::uri::RelativeUriExcessParentSegments_ERROR, + "http://a/b/c/d;p?q#s" }, + { "http://a/b/c/d;p?q", "g#s", true, + css::uri::RelativeUriExcessParentSegments_ERROR, + "http://a/b/c/g#s" }, + { "http://a/b/c/d;p?q", "g?y#s", true, + css::uri::RelativeUriExcessParentSegments_ERROR, + "http://a/b/c/g?y#s" }, + { "http://a/b/c/d;p?q", ";x", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://a/b/c/;x" }, + { "http://a/b/c/d;p?q", "g;x", true, + css::uri::RelativeUriExcessParentSegments_ERROR, + "http://a/b/c/g;x" }, + { "http://a/b/c/d;p?q", "g;x?y#s", true, + css::uri::RelativeUriExcessParentSegments_ERROR, + "http://a/b/c/g;x?y#s" }, + { "http://a/b/c/d;p?q", ".", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://a/b/c/" }, + { "http://a/b/c/d;p?q", "./", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://a/b/c/" }, + { "http://a/b/c/d;p?q", "..", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://a/b/" }, + { "http://a/b/c/d;p?q", "../", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://a/b/" }, + { "http://a/b/c/d;p?q", "../g", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://a/b/g" }, + { "http://a/b/c/d;p?q", "../..", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://a/" }, + { "http://a/b/c/d;p?q", "../../", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://a/" }, + { "http://a/b/c/d;p?q", "../../g", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://a/g" }, + { "http://a/b/c/d;p?q", "", true, + css::uri::RelativeUriExcessParentSegments_ERROR, + "http://a/b/c/d;p?q" }, + { "http://a/b/c/d;p?q", "../../../g", true, + css::uri::RelativeUriExcessParentSegments_ERROR, 0 }, + { "http://a/b/c/d;p?q", "../../../g", true, + css::uri::RelativeUriExcessParentSegments_RETAIN, "http://a/../g" }, + { "http://a/b/c/d;p?q", "../../../g", true, + css::uri::RelativeUriExcessParentSegments_REMOVE, "http://a/g" }, + { "http://a/b/c/d;p?q", "../../../../g", true, + css::uri::RelativeUriExcessParentSegments_ERROR, 0 }, + { "http://a/b/c/d;p?q", "../../../../g", true, + css::uri::RelativeUriExcessParentSegments_RETAIN, + "http://a/../../g" }, + { "http://a/b/c/d;p?q", "../../../../g", true, + css::uri::RelativeUriExcessParentSegments_REMOVE, "http://a/g" }, + { "http://a/b/c/d;p?q", "/./g", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://a/./g" }, + { "http://a/b/c/d;p?q", "/../g", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://a/../g" }, + { "http://a/b/c/d;p?q", "g.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://a/b/c/g." }, + { "http://a/b/c/d;p?q", ".g", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://a/b/c/.g" }, + { "http://a/b/c/d;p?q", "g..", true, + css::uri::RelativeUriExcessParentSegments_ERROR, + "http://a/b/c/g.." }, + { "http://a/b/c/d;p?q", "..g", true, + css::uri::RelativeUriExcessParentSegments_ERROR, + "http://a/b/c/..g" }, + { "http://a/b/c/d;p?q", "./../g", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://a/b/g" }, + { "http://a/b/c/d;p?q", "./g/.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://a/b/c/g/" }, + { "http://a/b/c/d;p?q", "g/./h", true, + css::uri::RelativeUriExcessParentSegments_ERROR, + "http://a/b/c/g/h" }, + { "http://a/b/c/d;p?q", "g/../h", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://a/b/c/h" }, + { "http://a/b/c/d;p?q", "g;x=1/./y", true, + css::uri::RelativeUriExcessParentSegments_ERROR, + "http://a/b/c/g;x=1/y" }, + { "http://a/b/c/d;p?q", "g;x=1/../y", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http://a/b/c/y" }, + { "http://a/b/c/d;p?q", "g?y/./x", true, + css::uri::RelativeUriExcessParentSegments_ERROR, + "http://a/b/c/g?y/./x" }, + { "http://a/b/c/d;p?q", "g?y/../x", true, + css::uri::RelativeUriExcessParentSegments_ERROR, + "http://a/b/c/g?y/../x" }, + { "http://a/b/c/d;p?q", "g#s/./x", true, + css::uri::RelativeUriExcessParentSegments_ERROR, + "http://a/b/c/g#s/./x" }, + { "http://a/b/c/d;p?q", "g#s/../x", true, + css::uri::RelativeUriExcessParentSegments_ERROR, + "http://a/b/c/g#s/../x" }, + { "http.://a/b/c/d;p?q", "http.:g", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "http.:g" }, + + { "scheme://a", "", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + { "scheme://a", ".", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + { "scheme://a", "./", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + { "scheme://a", "./.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + { "scheme://a", "././", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + { "scheme://a", "././.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + { "scheme://a", "x/..", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + { "scheme://a", "x/../", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + { "scheme://a", "x/../.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + { "scheme://a", "x/.././", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + { "scheme://a", "x/.././.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + { "scheme://a", "x/../././", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + { "scheme://a", "x/../././.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + { "scheme://a", "./x/..", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + { "scheme://a", "././x/..", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + { "scheme://a", "./././x/..", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + { "scheme://a", "./x/../.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + { "scheme://a", "./x/.././", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + { "scheme://a", "././x/.././.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + { "scheme://a", "././x/../././", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + { "scheme://a", "./././x/../././.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + + { "scheme://a/", "", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/", ".", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/", "./", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/", "./.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/", "././", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/", "././.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/", "x/..", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/", "x/../", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/", "x/../.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/", "x/.././", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/", "x/.././.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/", "x/../././", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/", "x/../././.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/", "./x/..", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/", "././x/..", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/", "./././x/..", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/", "./x/../.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/", "./x/.././", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/", "././x/.././.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/", "././x/../././", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/", "./././x/../././.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + + { "scheme://a/b", "", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b" }, + { "scheme://a/b", ".", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/b", "./", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/b", "./.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/b", "././", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/b", "././.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/b", "x/..", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/b", "x/../", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/b", "x/../.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/b", "x/.././", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/b", "x/.././.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/b", "x/../././", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/b", "x/../././.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/b", "./x/..", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/b", "././x/..", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/b", "./././x/..", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/b", "./x/../.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/b", "./x/.././", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/b", "././x/.././.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/b", "././x/../././", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + { "scheme://a/b", "./././x/../././.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/" }, + + { "scheme://a/b/", "", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b/" }, + { "scheme://a/b/", ".", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b/" }, + { "scheme://a/b/", "./", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b/" }, + { "scheme://a/b/", "./.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b/" }, + { "scheme://a/b/", "././", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b/" }, + { "scheme://a/b/", "././.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b/" }, + { "scheme://a/b/", "x/..", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b/" }, + { "scheme://a/b/", "x/../", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b/" }, + { "scheme://a/b/", "x/../.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b/" }, + { "scheme://a/b/", "x/.././", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b/" }, + { "scheme://a/b/", "x/.././.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b/" }, + { "scheme://a/b/", "x/../././", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b/" }, + { "scheme://a/b/", "x/../././.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b/" }, + { "scheme://a/b/", "./x/..", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b/" }, + { "scheme://a/b/", "././x/..", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b/" }, + { "scheme://a/b/", "./././x/..", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b/" }, + { "scheme://a/b/", "./x/../.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b/" }, + { "scheme://a/b/", "./x/.././", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b/" }, + { "scheme://a/b/", "././x/.././.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b/" }, + { "scheme://a/b/", "././x/../././", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b/" }, + { "scheme://a/b/", "./././x/../././.", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a/b/" }, + + { "scheme://a#s", "", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a" }, + { "scheme://a", "?q", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a?q" }, + { "scheme://a#s", "?q", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a?q" }, + { "scheme://a", "#s", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a#s" }, + { "scheme://a#s1", "#s2", true, + css::uri::RelativeUriExcessParentSegments_ERROR, "scheme://a#s2" } }; + for (std::size_t i = 0; i < sizeof data / sizeof data[0]; ++i) { + css::uno::Reference< css::uri::XUriReference > baseUriRef( + m_uriFactory->parse( + rtl::OUString::createFromAscii(data[i].baseUriReference))); + CPPUNIT_ASSERT(baseUriRef.is()); + css::uno::Reference< css::uri::XUriReference > uriRef( + m_uriFactory->parse( + rtl::OUString::createFromAscii(data[i].uriReference))); + CPPUNIT_ASSERT(uriRef.is()); + css::uno::Reference< css::uri::XUriReference > absolute( + m_uriFactory->makeAbsolute( + baseUriRef, uriRef, data[i].processSpecialBaseSegments, + data[i].excessParentSegments)); + TEST_ASSERT_EQUAL( + "testMakeAbsolute", i, data[i].uriReference, + data[i].absolute != 0, absolute.is()); + if (absolute.is()) { + TEST_ASSERT_EQUAL( + "testMakeAbsolute", i, data[i].uriReference, + rtl::OUString::createFromAscii(data[i].absolute), + absolute->getUriReference()); + } + } +} + +void Test::testMakeRelative() { + struct Data { + char const * baseUriReference; + char const * uriReference; + bool preferAuthorityOverRelativePath; + bool preferAbsoluteOverRelativePath; + bool encodeRetainedSpecialSegments; + char const * relative; + char const * absolute; + }; + Data data[] = { + { "scheme1://a/b/c", "scheme2://a/b/c?q#s", true, true, false, + "scheme2://a/b/c?q#s", 0 }, + { "scheme://a/b/c", "scheme:a/b/c?q#s", true, true, false, + "scheme:a/b/c?q#s", 0 }, + { "scheme://a/b/c", "", true, true, false, "", "scheme://a/b/c" }, + { "scheme://a/b/c", "//d/e/f", true, true, false, "//d/e/f", + "scheme://d/e/f" }, + { "scheme://a/b/c", "./e?q#s", true, true, false, "./e?q#s", + "scheme://a/b/e?q#s" }, + { "scheme://a/b", "scheme://a?q", true, true, false, "/?q", + "scheme://a/?q" }, + { "scheme://a/b", "scheme://a?q", true, false, false, "?q", + "scheme://a/?q" }, + { "scheme://a", "scheme://a?q", true, true, false, "?q", 0 }, + { "scheme://a/", "scheme://a?q", true, true, false, "?q", + "scheme://a/?q" }, + { "scheme://a", "scheme://a/?q", true, true, false, "?q", + "scheme://a?q" }, + { "scheme://a/", "scheme://a/?q", true, true, false, "?q", + "scheme://a/?q" }, + { "scheme://a?q", "scheme://a?q", true, true, false, "", 0 }, + { "scheme://a/?q", "scheme://a?q", true, true, false, "", + "scheme://a/?q" }, + { "scheme://a?q", "scheme://a/?q", true, true, false, "", + "scheme://a?q" }, + { "scheme://a/?q", "scheme://a/?q", true, true, false, "", 0 }, + { "scheme://a/b/c/d", "scheme://a//", true, true, false, "//a//", 0 }, + { "scheme://a/b/c/d", "scheme://a//", false, true, false, "../..//", + 0 }, + { "scheme://a/b/c/d", "scheme://a//", true, false, false, "../..//", + 0 }, + { "scheme://a/b/c/d", "scheme://a//", false, false, false, "../..//", + 0 }, + { "scheme://a/b/c/d", "scheme://a/e", true, true, false, "/e", 0 }, + { "scheme://a/b/c/d", "scheme://a/e", true, false, false, "../../e", + 0 }, + { "scheme://a/b/c/d/e", "scheme://a/b/f", true, true, false, "../../f", + 0 }, + { "scheme://a/b/c/d/e", "scheme://a/b", true, true, false, "/b", 0 }, + { "scheme://a/b/c/d/e", "scheme://a/b", true, false, false, + "../../../b", 0 }, + { "scheme://a/b/c/d/e", "scheme://a/b/", true, true, false, "../..", + 0 }, + { "scheme://a/b/c/d/e", "scheme://a/b/c", true, true, false, "../../c", + 0 }, + { "scheme://a/b/c/d/e", "scheme://a/b/c/", true, true, false, "..", 0 }, + { "scheme://a/b/", "scheme://a/b/c/d", true, true, false, "c/d", 0 }, + { "scheme://a/b/", "scheme://a/b/c/d/", true, true, false, "c/d/", 0 }, + { "scheme://a/b/c", "scheme://a/b//", true, true, false, ".//", 0 }, + { "scheme://a/b/c", "scheme://a/b//d", true, true, false, ".//d", 0 }, + { "scheme://a/b/c", "scheme://a/b//d//", true, true, false, ".//d//", + 0 }, + { "scheme://a/b/c", "scheme://a/b/d+:", true, true, false, "./d+:", 0 }, + { "scheme://a/b/c", "scheme://a/b/+d:", true, true, false, "+d:", 0 }, + { "scheme://a/b/c", "scheme://a/b/d#e:f", true, true, false, "d#e:f", + 0 }, + { "scheme://a/b/c/", "scheme://a/b/../d/.e/.", true, true, false, + "../../d/.e/.", + "scheme://a/d/.e/" }, + { "scheme://a/b/c/", "scheme://a/b/../d/.e/.", true, true, true, + "../%2E%2E/d/.e/%2E", "scheme://a/b/%2E%2E/d/.e/%2E" }, + { "scheme://auth/a/b", "scheme://auth//c/d", true, true, false, + "//auth//c/d", 0 }, + { "scheme://auth/a/b", "scheme://auth//c/d", false, true, false, + "..//c/d", 0 }, + { "scheme://auth/a/b", "scheme://auth/c/d", true, true, false, "/c/d", + 0 }, + { "scheme://auth/a/b", "scheme://auth/c/d", true, false, false, + "../c/d", 0 } }; + for (std::size_t i = 0; i < sizeof data / sizeof data[0]; ++i) { + css::uno::Reference< css::uri::XUriReference > baseUriRef( + m_uriFactory->parse( + rtl::OUString::createFromAscii(data[i].baseUriReference))); + CPPUNIT_ASSERT(baseUriRef.is()); + css::uno::Reference< css::uri::XUriReference > uriRef( + m_uriFactory->parse( + rtl::OUString::createFromAscii(data[i].uriReference))); + CPPUNIT_ASSERT(uriRef.is()); + css::uno::Reference< css::uri::XUriReference > relative( + m_uriFactory->makeRelative( + baseUriRef, uriRef, data[i].preferAuthorityOverRelativePath, + data[i].preferAbsoluteOverRelativePath, + data[i].encodeRetainedSpecialSegments)); + TEST_ASSERT_EQUAL( + "testMakeRelative", i, data[i].uriReference, + data[i].relative != 0, relative.is()); + if (relative.is()) { + TEST_ASSERT_EQUAL( + "testMakeRelative", i, data[i].uriReference, + rtl::OUString::createFromAscii(data[i].relative), + relative->getUriReference()); + css::uno::Reference< css::uri::XUriReference > absolute( + m_uriFactory->makeAbsolute( + baseUriRef, relative, true, + css::uri::RelativeUriExcessParentSegments_ERROR)); + CPPUNIT_ASSERT(absolute.is()); + TEST_ASSERT_EQUAL( + "testMakeRelative", i, data[i].uriReference, + rtl::OUString::createFromAscii( + data[i].absolute == 0 + ? data[i].uriReference : data[i].absolute), + absolute->getUriReference()); + } + } +} + +void Test::testVndSunStarExpand() { + struct Data { + char const * uriReference; + char const * expanded; + }; + Data data[] = { + { "vnd.sun.star.expand:", "" }, // liberally accepted + { "vnd.sun.star.expand:/", "/" }, // liberally accepted + { "vnd.sun.star.expand:%80", 0 }, + { "vnd.sun.star.expand:%5C$%5C%24%5C%5C", "$$\\" } }; + css::uno::Reference< css::util::XMacroExpander > expander( + m_context->getValueByName( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "/singletons/com.sun.star.util.theMacroExpander"))), + css::uno::UNO_QUERY_THROW); + for (std::size_t i = 0; i < sizeof data / sizeof data[0]; ++i) { + css::uno::Reference< css::uri::XUriReference > uriRef( + m_uriFactory->parse( + rtl::OUString::createFromAscii(data[i].uriReference))); + TEST_ASSERT_EQUAL( + "testVndSunStarExpand", i, data[i].uriReference, + data[i].expanded != 0, uriRef.is()); + if (uriRef.is()) { + css::uno::Reference< css::uri::XVndSunStarExpandUrlReference > + expandUrl(uriRef, css::uno::UNO_QUERY_THROW); + TEST_ASSERT_EQUAL( + "testVndSunStarExpand", i, data[i].uriReference, + rtl::OUString::createFromAscii(data[i].expanded), + expandUrl->expand(expander)); + } + } +} + +void Test::testVndSunStarScript() { + struct Parameter { + char const * key; + char const * value; + }; + std::size_t const parameterCount = 3; + struct Data { + char const * uriReference; + char const * name; + const bool normalized; + Parameter parameters[parameterCount]; + }; + Data data[] = { + { "vnd.sun.star.script:", 0, false, {} }, + { "vnd.sun.star.script:/", 0, false, {} }, + { "vnd.sun.star.script:/abc/def?ghi=jkl&mno=pqr", 0, false, {} }, + { "vnd.sun.star.script:abc%3fdef/ghi", "abc?def/ghi", false, {} }, + { "vnd.sun.star.script:name?a", 0, false, {} }, + { "vnd.sun.star.script:name?a=", "name", true, { { "a", "" }, { "A", 0 } } }, + { "vnd.sun.star.script:name?a=&", 0, true, {} }, + { "vnd.sun.star.script:name?key1=&%26=%3D&key1=hello", "name", true, + { { "key1", "" }, { "key2", 0 }, { "&", "=" } } } }; + for (std::size_t i = 0; i < sizeof data / sizeof data[0]; ++i) { + css::uno::Reference< css::uri::XUriReference > uriRef( + m_uriFactory->parse( + rtl::OUString::createFromAscii(data[i].uriReference))); + TEST_ASSERT_EQUAL( + "testVndSunStarScript", i, data[i].uriReference, data[i].name != 0, + uriRef.is()); + if (uriRef.is()) { + css::uno::Reference< css::uri::XVndSunStarScriptUrlReference > + scriptUrl(uriRef, css::uno::UNO_QUERY_THROW); + TEST_ASSERT_EQUAL( + "testVndSunStarScript", i, data[i].uriReference, + rtl::OUString::createFromAscii(data[i].uriReference), + scriptUrl->getUriReference()); + TEST_ASSERT_EQUAL( + "testVndSunStarScript", i, data[i].uriReference, + rtl::OUString::createFromAscii(data[i].name), + scriptUrl->getName()); + rtl::OUString originalReference(uriRef->getUriReference()); + for (std::size_t j = 0; j < parameterCount; ++j) { + if (data[i].parameters[j].key != 0) { + TEST_ASSERT_EQUAL( + "testVndSunStarScript", + static_cast< double >(i) + + static_cast< double >(j) / 10.0, + data[i].uriReference, + data[i].parameters[j].value != 0, + scriptUrl->hasParameter( + rtl::OUString::createFromAscii( + data[i].parameters[j].key))); + TEST_ASSERT_EQUAL( + "testVndSunStarScript", + static_cast< double >(i) + + static_cast< double >(j) / 10.0, + data[i].uriReference, + rtl::OUString::createFromAscii( + data[i].parameters[j].value), + scriptUrl->getParameter( + rtl::OUString::createFromAscii( + data[i].parameters[j].key))); + + // setting the parameter to its original value should not change + // the overall uri reference (provided it was normalized before) + if ( data[i].normalized ) { + if ( scriptUrl->hasParameter(rtl::OUString::createFromAscii( + data[i].parameters[j].key)) ) { + scriptUrl->setParameter( + rtl::OUString::createFromAscii( + data[i].parameters[j].key), + scriptUrl->getParameter( + rtl::OUString::createFromAscii( + data[i].parameters[j].key))); + TEST_ASSERT_EQUAL( + "testVndSunStarScript", + static_cast< double >(i) + + static_cast< double >(j) / 10.0, + ::rtl::OUString::createFromAscii("setParameter"), + originalReference, + uriRef->getUriReference()); + } + } + } + } + if ( data[i].normalized ) { + scriptUrl->setName(scriptUrl->getName()); + TEST_ASSERT_EQUAL( + "testVndSunStarScript", + i, + ::rtl::OUString::createFromAscii("setName"), + originalReference, + uriRef->getUriReference()); + } + } + } + + css::uno::Reference< css::uri::XUriReference > uriRef( + m_uriFactory->parse( + rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( + "vnd.sun.star.script:Hello?location=Library.Module"))), + css::uno::UNO_SET_THROW); + css::uno::Reference< css::uri::XVndSunStarScriptUrlReference > + scriptUrl(uriRef, css::uno::UNO_QUERY_THROW); + + scriptUrl->setParameter( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "location")), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "foo"))); + TEST_ASSERT_EQUAL( + "testVndSunStarScript", (sal_Int32)10, (sal_Int32)1, + uriRef->getUriReference(), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.script:Hello?location=foo"))); + + scriptUrl->setParameter( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "language")), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "StarBasic"))); + TEST_ASSERT_EQUAL( + "testVndSunStarScript", (sal_Int32)10, (sal_Int32)2, + uriRef->getUriReference(), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.script:Hello?location=foo&language=StarBasic"))); + + + bool caughtExpected = false; + try { + scriptUrl->setName(::rtl::OUString()); + } + catch( const css::lang::IllegalArgumentException& ) { + caughtExpected = true; + } + TEST_ASSERT_EQUAL( + "testVndSunStarScript", + ::rtl::OUString::createFromAscii("illegal arguments"), + ::rtl::OUString::createFromAscii("name"), + caughtExpected, + true); + + caughtExpected = false; + try { + scriptUrl->setParameter( + ::rtl::OUString(), + ::rtl::OUString::createFromAscii("non-empty")); + } + catch( const css::lang::IllegalArgumentException& ) { + caughtExpected = true; + } + TEST_ASSERT_EQUAL( + "testVndSunStarScript", + ::rtl::OUString::createFromAscii("illegal arguments"), + ::rtl::OUString::createFromAscii("parameter"), + caughtExpected, + true); +} + +void Test::testTranslator() { + struct Data { + char const * externalUriReference; + char const * internalUriReference; + bool toInternal; + }; + Data data[] = { + { "", "", true }, + { "#fragment", "#fragment", true }, + { "segment/segment?query#fragment", "segment/segment?query#fragment", + true }, + { "/segment/segment?query#fragment", "/segment/segment?query#fragment", + true }, + { "//authority/segment?query#fragment", + "//authority/segment?query#fragment", true }, + { "foo:bar#fragment", "foo:bar#fragment", true }, + { "file:///abc/def", "file:///abc/def", true }, + { "file:///abc/%FEef", "file:///abc/%feef", false }, + { "file:///abc/%80%80ef", "file:///abc/%80%80ef", false }, + { "file:///abc/%ED%A0%80%ED%B0%80ef", + "file:///abc/%ED%A0%80%ED%B0%80ef", false }, + { "file:///abc/%25.ef", "file:///abc/%.ef", false }, + { "file:///abc/%25ef", "file:///abc/%25ef", true } }; + css::uno::Reference< css::uri::XExternalUriReferenceTranslator > + translator(css::uri::ExternalUriReferenceTranslator::create(m_context)); + for (std::size_t i = 0; i < sizeof data / sizeof data[0]; ++i) { + if (data[i].toInternal) { + TEST_ASSERT_EQUAL( + "testTranslator, translateToInternal", i, + data[i].externalUriReference, + rtl::OUString::createFromAscii(data[i].internalUriReference), + translator->translateToInternal( + rtl::OUString::createFromAscii( + data[i].externalUriReference))); + } + TEST_ASSERT_EQUAL( + "testTranslator, translateToExternal", i, + data[i].internalUriReference, + rtl::OUString::createFromAscii(data[i].externalUriReference), + translator->translateToExternal( + rtl::OUString::createFromAscii(data[i].internalUriReference))); + } +} + +void Test::testPkgUrlFactory() { + struct Data { + char const * authority; + char const * result; + }; + Data data[] = { + { "a/b/c", 0 }, + { "file:///#foo", 0 }, + { "file:///a%25b%2fc/d~e&f@g?h", + "vnd.sun.star.pkg://file:%2F%2F%2Fa%2525b%252fc%2Fd~e&f@g%3Fh" } }; + css::uno::Reference< css::uri::XVndSunStarPkgUrlReferenceFactory > factory( + css::uri::VndSunStarPkgUrlReferenceFactory::create(m_context)); + for (std::size_t i = 0; i < sizeof data / sizeof data[0]; ++i) { + css::uno::Reference< css::uri::XUriReference > url( + factory->createVndSunStarPkgUrlReference( + m_uriFactory->parse( + rtl::OUString::createFromAscii(data[i].authority)))); + TEST_ASSERT_EQUAL( + "testVndSunStarPkgFactory", i, data[i].authority, + data[i].result != 0, static_cast< bool >(url.is())); + if (data[i].result != 0) { + TEST_ASSERT_EQUAL( + "testVndSunStarPkgFactory", i, data[i].authority, + rtl::OUString::createFromAscii(data[i].result), + url->getUriReference()); + } + } +} + +CPPUNIT_TEST_SUITE_REGISTRATION(Test); + +} + +CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/stoc/test/uriproc/version.map b/stoc/test/uriproc/version.map new file mode 100644 index 000000000000..3308588ef6f8 --- /dev/null +++ b/stoc/test/uriproc/version.map @@ -0,0 +1,34 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +UDK_3_0_0 { + global: + cppunitTestPlugIn; + + local: + *; +}; diff --git a/stoc/unosdk.mk b/stoc/unosdk.mk new file mode 100644 index 000000000000..e82425745614 --- /dev/null +++ b/stoc/unosdk.mk @@ -0,0 +1,34 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + +PPATH=inc + +FILES= \ + $(PPATH)\stoc\component.hxx + +unosdk: $(FILES) + docpp -H -m -f -u -d ..\..\doc\stoc $(FILES) diff --git a/stoc/util/makefile.mk b/stoc/util/makefile.mk new file mode 100644 index 000000000000..4243d45511fe --- /dev/null +++ b/stoc/util/makefile.mk @@ -0,0 +1,96 @@ +#************************************************************************* +# +# 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= bootstrap +TARGET = bootstrap.uno +ENABLE_EXCEPTIONS=TRUE + +# --- openoffice.org.orig/Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +DLLPRE = + +# ------------------------------------------------------------------ + +SHL1TARGET= $(TARGET) + +LIB1TARGET= $(SLB)$/$(TARGET).lib +LIB1FILES= $(SLB)$/bootstrap.lib \ + $(SLB)$/security.lib \ + $(SLB)$/servicemgr.lib \ + $(SLB)$/simplereg.lib \ + $(SLB)$/nestedreg.lib \ + $(SLB)$/implreg.lib \ + $(SLB)$/shlibloader.lib \ + $(SLB)$/regtypeprov.lib \ + $(SLB)$/typemgr.lib + +SHL1VERSIONMAP = $(SOLARENV)/src/unloadablecomponent.map + +SHL1STDLIBS= \ + $(CPPULIB) \ + $(SALHELPERLIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) \ + $(REGLIB) + +SHL1DEPN= +SHL1IMPLIB= i$(TARGET) +SHL1LIBS= $(SLB)$/$(TARGET).lib +SHL1DEF= $(MISC)$/$(SHL1TARGET).def +SHL1RPATH= URELIB + +DEF1NAME= $(SHL1TARGET) + +SHL2TARGET= stocservices.uno + +LIB2TARGET= $(SLB)$/stocservices.uno.lib +LIB2FILES= \ + $(SLB)$/stocservices.lib \ + $(SLB)$/typeconverter.lib \ + $(SLB)$/uriproc.lib + +SHL2VERSIONMAP = $(SOLARENV)/src/unloadablecomponent.map + +SHL2STDLIBS= \ + $(CPPULIB) \ + $(CPPUHELPERLIB) \ + $(SALLIB) + +SHL2DEPN= +SHL2IMPLIB= istocservices.uno +SHL2LIBS= $(SLB)$/stocservices.uno.lib +SHL2DEF= $(MISC)$/$(SHL2TARGET).def +SHL2RPATH= URELIB + +DEF2NAME= $(SHL2TARGET) + +# --- openoffice.org.orig/Targets ------------------------------------------------------ + +.INCLUDE : target.mk + |