1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_javaunohelper.hxx"
30 
31 #include <osl/diagnose.h>
32 #include <osl/module.h>
33 
34 #include <uno/environment.hxx>
35 #include <uno/mapping.hxx>
36 
37 #include <cppuhelper/factory.hxx>
38 #include <cppuhelper/servicefactory.hxx>
39 #include <cppuhelper/component_context.hxx>
40 
41 #include <com/sun/star/beans/XPropertySet.hpp>
42 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
43 #include <com/sun/star/lang/XServiceInfo.hpp>
44 #include <com/sun/star/registry/XRegistryKey.hpp>
45 
46 #include "jni.h"
47 #include "jvmaccess/virtualmachine.hxx"
48 #include "jvmaccess/unovirtualmachine.hxx"
49 
50 #include "vm.hxx"
51 
52 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
53 
54 
55 using namespace ::com::sun::star;
56 using namespace ::com::sun::star::uno;
57 using ::rtl::OString;
58 using ::rtl::OUString;
59 
60 /*
61  * Class:     com_sun_star_comp_helper_SharedLibraryLoader
62  * Method:    component_writeInfo
63  * Signature: (Ljava/lang/String;Lcom/sun/star/lang/XMultiServiceFactory;Lcom/sun/star/registry/XRegistryKey;)Z
64  */
65 extern "C" JNIEXPORT jboolean JNICALL
66 Java_com_sun_star_comp_helper_SharedLibraryLoader_component_1writeInfo(
67     JNIEnv * pJEnv, jclass, jstring jLibName, jobject jSMgr,
68     jobject jRegKey, jobject loader )
69 {
70 	sal_Bool bRet = sal_False;
71 
72 	const jchar* pJLibName = pJEnv->GetStringChars( jLibName, NULL );
73 	OUString aLibName( pJLibName );
74 	pJEnv->ReleaseStringChars( jLibName, pJLibName);
75 
76 	oslModule lib = osl_loadModule( aLibName.pData, SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL );
77 	if (lib)
78 	{
79 		// ========================= LATEST VERSION =========================
80 		OUString aGetEnvName( RTL_CONSTASCII_USTRINGPARAM(COMPONENT_GETENV) );
81 		oslGenericFunction pSym =
82             osl_getFunctionSymbol( lib, aGetEnvName.pData );
83 		if (pSym)
84 		{
85 			Environment java_env, loader_env;
86 
87 			const sal_Char * pEnvTypeName = 0;
88 			(*((component_getImplementationEnvironmentFunc)pSym))(
89                 &pEnvTypeName, (uno_Environment **)&loader_env );
90 			if (! loader_env.is())
91             {
92                 OUString aEnvTypeName( OUString::createFromAscii( pEnvTypeName ) );
93 				uno_getEnvironment( (uno_Environment **)&loader_env, aEnvTypeName.pData, 0 );
94             }
95 
96             // create vm access
97             ::rtl::Reference< ::jvmaccess::UnoVirtualMachine > vm_access(
98                 ::javaunohelper::create_vm_access( pJEnv, loader ) );
99             OUString java_env_name = OUSTR(UNO_LB_JAVA);
100             uno_getEnvironment(
101                 (uno_Environment **)&java_env, java_env_name.pData, vm_access.get() );
102 
103 			OUString aWriteInfoName( RTL_CONSTASCII_USTRINGPARAM(COMPONENT_WRITEINFO) );
104             pSym = osl_getFunctionSymbol( lib, aWriteInfoName.pData );
105 			if (pSym)
106 			{
107 				if (loader_env.is() && java_env.is())
108 				{
109 					Mapping java2dest(java_env.get(), loader_env.get());
110 
111 					if ( java2dest.is() )
112 					{
113 						void * pSMgr =
114                             java2dest.mapInterface(
115                                 jSMgr, getCppuType((Reference< lang::XMultiServiceFactory > *) 0) );
116 						void * pKey =
117                             java2dest.mapInterface(
118                                 jRegKey, getCppuType((Reference< registry::XRegistryKey > *) 0) );
119 
120                         uno_ExtEnvironment * env = loader_env.get()->pExtEnv;
121 						if (pKey)
122 						{
123 							bRet = (*((component_writeInfoFunc)pSym))( pSMgr, pKey );
124 
125 							if (env)
126                                 (*env->releaseInterface)( env, pKey );
127 						}
128 
129 						if (pSMgr && env)
130 							(*env->releaseInterface)( env, pSMgr );
131 					}
132 				}
133 			}
134 		}
135 	}
136 
137 	return bRet == sal_False? JNI_FALSE : JNI_TRUE;
138 }
139 
140 /*
141  * Class:     com_sun_star_comp_helper_SharedLibraryLoader
142  * Method:    component_getFactory
143  * Signature: (Ljava/lang/String;Ljava/lang/String;Lcom/sun/star/lang/XMultiServiceFactory;Lcom/sun/star/registry/XRegistryKey;)Ljava/lang/Object;
144  */
145 extern "C" JNIEXPORT jobject JNICALL
146 Java_com_sun_star_comp_helper_SharedLibraryLoader_component_1getFactory(
147     JNIEnv * pJEnv, jclass, jstring jLibName, jstring jImplName,
148     jobject jSMgr, jobject jRegKey, jobject loader )
149 {
150 	const jchar* pJLibName = pJEnv->GetStringChars(jLibName, NULL);
151 	OUString aLibName( pJLibName );
152 	pJEnv->ReleaseStringChars( jLibName, pJLibName);
153 
154     aLibName += OUString( RTL_CONSTASCII_USTRINGPARAM(SAL_DLLEXTENSION) );
155 
156 	jobject joSLL_cpp = 0;
157 
158 	oslModule lib = osl_loadModule( aLibName.pData, SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL );
159 	if (lib)
160 	{
161 		// ========================= LATEST VERSION =========================
162 		OUString aGetEnvName( RTL_CONSTASCII_USTRINGPARAM(COMPONENT_GETENV) );
163 		oslGenericFunction pSym =
164             osl_getFunctionSymbol( lib, aGetEnvName.pData );
165 		if (pSym)
166 		{
167 			Environment java_env, loader_env;
168 
169 			const sal_Char * pEnvTypeName = 0;
170 			(*((component_getImplementationEnvironmentFunc)pSym))(
171                 &pEnvTypeName, (uno_Environment **)&loader_env );
172 
173             if (! loader_env.is())
174             {
175                 OUString aEnvTypeName( OUString::createFromAscii( pEnvTypeName ) );
176 				uno_getEnvironment( (uno_Environment **)&loader_env, aEnvTypeName.pData, 0 );
177             }
178 
179             // create vm access
180             ::rtl::Reference< ::jvmaccess::UnoVirtualMachine > vm_access(
181                 ::javaunohelper::create_vm_access( pJEnv, loader ) );
182             OUString java_env_name = OUSTR(UNO_LB_JAVA);
183             uno_getEnvironment(
184                 (uno_Environment **)&java_env, java_env_name.pData, vm_access.get() );
185 
186 			OUString aGetFactoryName( RTL_CONSTASCII_USTRINGPARAM(COMPONENT_GETFACTORY) );
187             pSym = osl_getFunctionSymbol( lib, aGetFactoryName.pData );
188 			if (pSym)
189 			{
190 				if (loader_env.is() && java_env.is())
191 				{
192 					Mapping java2dest( java_env.get(), loader_env.get() );
193 					Mapping dest2java( loader_env.get(), java_env.get() );
194 
195 					if (dest2java.is() && java2dest.is())
196 					{
197 						void * pSMgr =
198                             java2dest.mapInterface(
199                                 jSMgr, ::getCppuType((Reference< lang::XMultiServiceFactory > *) 0) );
200 						void * pKey =
201                             java2dest.mapInterface(
202                                 jRegKey, ::getCppuType((Reference< registry::XRegistryKey > *) 0) );
203 
204 						const char* pImplName = pJEnv->GetStringUTFChars( jImplName, NULL );
205 
206 						void * pSSF = (*((component_getFactoryFunc)pSym))(
207                             pImplName, pSMgr, pKey );
208 
209 						pJEnv->ReleaseStringUTFChars( jImplName, pImplName );
210 
211                         uno_ExtEnvironment * env = loader_env.get()->pExtEnv;
212 
213 						if (pKey && env)
214 							(*env->releaseInterface)( env, pKey );
215 						if (pSMgr && env)
216 							(*env->releaseInterface)( env, pSMgr );
217 
218 						if (pSSF)
219 						{
220                             jobject jglobal = (jobject) dest2java.mapInterface(
221                                 pSSF, getCppuType((Reference< XInterface > *) 0) );
222 							joSLL_cpp = pJEnv->NewLocalRef( jglobal );
223                             pJEnv->DeleteGlobalRef( jglobal );
224 							if (env)
225                                 (*env->releaseInterface)( env, pSSF );
226 						}
227 					}
228 				}
229 			}
230 		}
231 	}
232 
233 	return joSLL_cpp;
234 }
235 
236 /*
237  * Class:     com_sun_star_comp_helper_RegistryServiceFactory
238  * Method:    createRegistryServiceFactory
239  * Signature: (Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/Object;
240  */
241 extern "C" JNIEXPORT jobject JNICALL
242 Java_com_sun_star_comp_helper_RegistryServiceFactory_createRegistryServiceFactory(
243     JNIEnv * pJEnv, jclass, jstring jWriteRegFile,
244     jstring jReadRegFile, jboolean jbReadOnly, jobject loader )
245 {
246 	jobject joRegServiceFac = 0;
247 
248     try
249     {
250 		OUString aWriteRegFile;
251 		OUString aReadRegFile;
252 
253 		sal_Bool bReadOnly = jbReadOnly == JNI_FALSE ? sal_False : sal_True;
254 
255 		if (jReadRegFile) {
256 			const jchar* pjReadRegFile = pJEnv->GetStringChars(jReadRegFile, NULL);
257 			aReadRegFile = OUString(pjReadRegFile);
258 			pJEnv->ReleaseStringChars(jReadRegFile, pjReadRegFile);
259 		}
260 
261 		if (jWriteRegFile) {
262 			const jchar * pjWriteRegFile = pJEnv->GetStringChars(jWriteRegFile, NULL);
263 			aWriteRegFile = OUString(pjWriteRegFile);
264 			pJEnv->ReleaseStringChars(jWriteRegFile, pjWriteRegFile);
265 		}
266 
267         // bootstrap
268 		Reference< lang::XMultiServiceFactory > rMSFac;
269 		if (aReadRegFile.getLength() == 0)
270 			rMSFac = ::cppu::createRegistryServiceFactory( aWriteRegFile, bReadOnly);
271 		else
272 			rMSFac = ::cppu::createRegistryServiceFactory(aWriteRegFile, aReadRegFile, bReadOnly);
273 
274         Reference< beans::XPropertySet > xProps(
275             rMSFac, UNO_QUERY_THROW );
276         Reference< XComponentContext > xContext(
277             xProps->getPropertyValue( OUSTR("DefaultContext") ), UNO_QUERY_THROW );
278 
279         // create vm access
280         ::rtl::Reference< ::jvmaccess::UnoVirtualMachine > vm_access(
281             ::javaunohelper::create_vm_access( pJEnv, loader ) );
282         // wrap vm singleton entry
283         xContext = ::javaunohelper::install_vm_singleton( xContext, vm_access );
284         rMSFac.set( xContext->getServiceManager(), UNO_QUERY_THROW );
285 
286         // get uno envs
287 	    OUString aCurrentEnv(RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME));
288         OUString java_env_name = OUSTR(UNO_LB_JAVA);
289         Environment java_env, curr_env;
290 	    uno_getEnvironment((uno_Environment **)&curr_env, aCurrentEnv.pData, NULL);
291         uno_getEnvironment( (uno_Environment **)&java_env, java_env_name.pData, vm_access.get() );
292 
293 		Mapping curr_java(curr_env.get(), java_env.get());
294 		if (! curr_java.is())
295         {
296             throw RuntimeException(
297                 OUSTR("no C++ <-> Java mapping available!"), Reference< XInterface >() );
298         }
299 
300 		jobject joGlobalRegServiceFac =
301             (jobject)curr_java.mapInterface(
302                 rMSFac.get(),
303                 getCppuType((Reference< lang::XMultiServiceFactory > *)0) );
304         joRegServiceFac = pJEnv->NewLocalRef( joGlobalRegServiceFac );
305   		pJEnv->DeleteGlobalRef(joGlobalRegServiceFac);
306     }
307     catch (Exception & exc)
308     {
309         jclass c = pJEnv->FindClass( "com/sun/star/uno/RuntimeException" );
310         if (0 != c)
311         {
312             OString cstr( ::rtl::OUStringToOString(
313                               exc.Message, RTL_TEXTENCODING_JAVA_UTF8 ) );
314             OSL_TRACE( __FILE__": forwarding Exception: %s", cstr.getStr() );
315             pJEnv->ThrowNew( c, cstr.getStr() );
316         }
317         return 0;
318     }
319 
320 	OSL_TRACE("javaunohelper.cxx: object %i", joRegServiceFac);
321 
322     return joRegServiceFac;
323 }
324