1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_unotools.hxx"
26 
27 #include <unotools/componentfactory.hxx>
28 #include <comphelper/processfactory.hxx>
29 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
30 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
31 
32 #ifndef _COM_SUN_STAR_REGISTRY_XREGISTRYKEY_HDL_
33 #include <com/sun/star/registry/XRegistryKey.hpp>
34 #endif
35 
36 #include <cppuhelper/factory.hxx>
37 
38 #include <uno/environment.h>
39 #include <uno/mapping.hxx>
40 
41 #include <rtl/ustring.hxx>
42 #include <osl/module.h>
43 
44 
45 
46 
47 using namespace ::com::sun::star;
48 using namespace ::com::sun::star::uno;
49 using namespace ::com::sun::star::lang;
50 using namespace ::com::sun::star::registry;
51 using namespace ::rtl;
52 
53 
54 namespace utl
55 {
56 
getComponentInstance(const OUString & rLibraryName,const OUString & rImplementationName)57 Reference< XInterface > getComponentInstance(
58 			const OUString & rLibraryName,
59 			const OUString & rImplementationName
60 			)
61 {
62 	Reference< XInterface > xI;
63 	Reference< XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory();
64 	if ( xMSF.is() )
65 		xI = xMSF->createInstance( rImplementationName );
66 	if( !xI.is() )
67 	{
68 		Reference< XSingleServiceFactory > xSSF =
69 			loadLibComponentFactory( rLibraryName, rImplementationName,
70 			Reference< XMultiServiceFactory >(), Reference< XRegistryKey >() );
71 		xI = xSSF->createInstance();
72 	}
73 	return xI;
74 }
75 
76 
loadLibComponentFactory(const OUString & rLibName,const OUString & rImplName,const Reference<XMultiServiceFactory> & xSF,const Reference<XRegistryKey> & xKey)77 Reference< XSingleServiceFactory > loadLibComponentFactory(
78 			const OUString & rLibName,
79 			const OUString & rImplName,
80 			const Reference< XMultiServiceFactory > & xSF,
81 			const Reference< XRegistryKey > & xKey
82 			)
83 {
84 	Reference< XSingleServiceFactory > xRet;
85 
86 	oslModule lib = osl_loadModule( rLibName.pData, SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL );
87 	if (lib)
88 	{
89 		void * pSym;
90 
91 		// ========================= LATEST VERSION =========================
92 		OUString aGetEnvName( RTL_CONSTASCII_USTRINGPARAM(COMPONENT_GETENV) );
93 		if (pSym = osl_getSymbol( lib, aGetEnvName.pData ))
94 		{
95 			uno_Environment * pCurrentEnv = 0;
96 			uno_Environment * pEnv = 0;
97 			const sal_Char * pEnvTypeName = 0;
98 			(*((component_getImplementationEnvironmentFunc)pSym))( &pEnvTypeName, &pEnv );
99 
100 			sal_Bool bNeedsMapping =
101 				(pEnv || 0 != rtl_str_compare( pEnvTypeName, CPPU_CURRENT_LANGUAGE_BINDING_NAME ));
102 
103 			OUString aEnvTypeName( OUString::createFromAscii( pEnvTypeName ) );
104 
105 			if (bNeedsMapping)
106 			{
107 				if (! pEnv)
108 					uno_getEnvironment( &pEnv, aEnvTypeName.pData, 0 );
109 				if (pEnv)
110 				{
111 					OUString aCppEnvTypeName( RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME) );
112 					uno_getEnvironment( &pCurrentEnv, aCppEnvTypeName.pData, 0 );
113 					if (pCurrentEnv)
114 						bNeedsMapping = (pEnv != pCurrentEnv);
115 				}
116 			}
117 
118 			OUString aGetFactoryName( RTL_CONSTASCII_USTRINGPARAM(COMPONENT_GETFACTORY) );
119 			if (pSym = osl_getSymbol( lib, aGetFactoryName.pData ))
120 			{
121 				OString aImplName( OUStringToOString( rImplName, RTL_TEXTENCODING_ASCII_US ) );
122 
123 				if (bNeedsMapping)
124 				{
125 					if (pEnv && pCurrentEnv)
126 					{
127 						Mapping aCurrent2Env( pCurrentEnv, pEnv );
128 						Mapping aEnv2Current( pEnv, pCurrentEnv );
129 
130 						if (aCurrent2Env.is() && aEnv2Current.is())
131 						{
132 							void * pSMgr = aCurrent2Env.mapInterface(
133 								xSF.get(), ::getCppuType( (const Reference< XMultiServiceFactory > *)0 ) );
134 							void * pKey = aCurrent2Env.mapInterface(
135 								xKey.get(), ::getCppuType( (const Reference< XRegistryKey > *)0 ) );
136 
137 							void * pSSF = (*((component_getFactoryFunc)pSym))(
138 								aImplName.getStr(), pSMgr, pKey );
139 
140 							if (pKey)
141 								(*pEnv->pExtEnv->releaseInterface)( pEnv->pExtEnv, pKey );
142 							if (pSMgr)
143 								(*pEnv->pExtEnv->releaseInterface)( pEnv->pExtEnv, pSMgr );
144 
145 							if (pSSF)
146 							{
147 								aEnv2Current.mapInterface(
148 									reinterpret_cast< void ** >( &xRet ),
149 									pSSF, ::getCppuType( (const Reference< XSingleServiceFactory > *)0 ) );
150 								(*pEnv->pExtEnv->releaseInterface)( pEnv->pExtEnv, pSSF );
151 							}
152 						}
153 					}
154 				}
155 				else
156 				{
157 					XSingleServiceFactory * pRet = (XSingleServiceFactory *)
158 						(*((component_getFactoryFunc)pSym))(
159 							aImplName.getStr(), xSF.get(), xKey.get() );
160 					if (pRet)
161 					{
162 						xRet = pRet;
163 						pRet->release();
164 					}
165 				}
166 			}
167 
168 			if (pEnv)
169 				(*pEnv->release)( pEnv );
170 			if (pCurrentEnv)
171 				(*pCurrentEnv->release)( pCurrentEnv );
172 		}
173 
174 
175 		if (! xRet.is())
176 			osl_unloadModule( lib );
177 	}
178 
179 	return xRet;
180 }
181 
182 }	// namespace utl
183