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 
33 #include "rtl/alloc.h"
34 #include "rtl/bootstrap.hxx"
35 #include "rtl/string.hxx"
36 
37 #include "uno/mapping.hxx"
38 #include "uno/environment.hxx"
39 
40 #include "cppuhelper/bootstrap.hxx"
41 
42 #include "com/sun/star/lang/XComponent.hpp"
43 #include "com/sun/star/lang/XSingleComponentFactory.hpp"
44 
45 #include "jni.h"
46 #include "jvmaccess/virtualmachine.hxx"
47 #include "jvmaccess/unovirtualmachine.hxx"
48 
49 #include "vm.hxx"
50 
51 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
52 
53 
54 using namespace ::com::sun::star;
55 using namespace ::com::sun::star::uno;
56 using ::rtl::OString;
57 using ::rtl::OUString;
58 
59 namespace javaunohelper
60 {
61 
62 inline ::rtl::OUString jstring_to_oustring( jstring jstr, JNIEnv * jni_env )
63 {
64     OSL_ASSERT( sizeof (sal_Unicode) == sizeof (jchar) );
65     jsize len = jni_env->GetStringLength( jstr );
66     rtl_uString * ustr =
67         (rtl_uString *)rtl_allocateMemory( sizeof (rtl_uString) + (len * sizeof (sal_Unicode)) );
68     jni_env->GetStringRegion( jstr, 0, len, ustr->buffer );
69     OSL_ASSERT( JNI_FALSE == jni_env->ExceptionCheck() );
70     ustr->refCount = 1;
71     ustr->length = len;
72     ustr->buffer[ len ] = '\0';
73     return ::rtl::OUString( ustr, SAL_NO_ACQUIRE );
74 }
75 
76 }
77 
78 //==================================================================================================
79 extern "C" JNIEXPORT jobject JNICALL Java_com_sun_star_comp_helper_Bootstrap_cppuhelper_1bootstrap(
80     JNIEnv * jni_env, jclass, jstring juno_rc, jobjectArray jpairs,
81     jobject loader )
82 {
83     try
84     {
85         if (0 != jpairs)
86         {
87             jsize nPos = 0, len = jni_env->GetArrayLength( jpairs );
88             while (nPos < len)
89             {
90                 // name
91                 jstring jstr = (jstring)jni_env->GetObjectArrayElement( jpairs, nPos );
92                 if (JNI_FALSE != jni_env->ExceptionCheck())
93                 {
94                     jni_env->ExceptionClear();
95                     throw RuntimeException(
96                         OUSTR("index out of bounds?!"), Reference< XInterface >() );
97                 }
98                 if (0 != jstr)
99                 {
100                     OUString name( ::javaunohelper::jstring_to_oustring( jstr, jni_env ) );
101                     // value
102                     jstr = (jstring)jni_env->GetObjectArrayElement( jpairs, nPos +1 );
103                     if (JNI_FALSE != jni_env->ExceptionCheck())
104                     {
105                         jni_env->ExceptionClear();
106                         throw RuntimeException(
107                             OUSTR("index out of bounds?!"), Reference< XInterface >() );
108                     }
109                     if (0 != jstr)
110                     {
111                         OUString value( ::javaunohelper::jstring_to_oustring( jstr, jni_env ) );
112 
113                         // set bootstrap parameter
114                         ::rtl::Bootstrap::set( name, value );
115                     }
116                 }
117                 nPos += 2;
118             }
119         }
120 
121         // bootstrap uno
122         Reference< XComponentContext > xContext;
123         if (0 == juno_rc)
124         {
125             xContext = ::cppu::defaultBootstrap_InitialComponentContext();
126         }
127         else
128         {
129             OUString uno_rc( ::javaunohelper::jstring_to_oustring( juno_rc, jni_env ) );
130             xContext = ::cppu::defaultBootstrap_InitialComponentContext( uno_rc );
131         }
132 
133         // create vm access
134         ::rtl::Reference< ::jvmaccess::UnoVirtualMachine > vm_access(
135             ::javaunohelper::create_vm_access( jni_env, loader ) );
136         // wrap vm singleton entry
137         xContext = ::javaunohelper::install_vm_singleton( xContext, vm_access );
138 
139         // get uno envs
140 	    OUString cpp_env_name = OUSTR(CPPU_CURRENT_LANGUAGE_BINDING_NAME);
141         OUString java_env_name = OUSTR(UNO_LB_JAVA);
142         Environment java_env, cpp_env;
143 	    uno_getEnvironment((uno_Environment **)&cpp_env, cpp_env_name.pData, NULL);
144         uno_getEnvironment( (uno_Environment **)&java_env, java_env_name.pData, vm_access.get() );
145 
146         // map to java
147         Mapping mapping( cpp_env.get(), java_env.get() );
148         if (! mapping.is())
149         {
150             Reference< lang::XComponent > xComp( xContext, UNO_QUERY );
151             if (xComp.is())
152                 xComp->dispose();
153             throw RuntimeException(
154                 OUSTR("cannot get mapping C++ <-> Java!"),
155                 Reference< XInterface >() );
156         }
157 
158         jobject jret = (jobject)mapping.mapInterface( xContext.get(), ::getCppuType( &xContext ) );
159         jobject jlocal = jni_env->NewLocalRef( jret );
160         jni_env->DeleteGlobalRef( jret );
161 
162         return jlocal;
163     }
164     catch (RuntimeException & exc)
165     {
166         jclass c = jni_env->FindClass( "com/sun/star/uno/RuntimeException" );
167         if (0 != c)
168         {
169             OString cstr( ::rtl::OUStringToOString(
170                               exc.Message, RTL_TEXTENCODING_JAVA_UTF8 ) );
171             OSL_TRACE( __FILE__": forwarding RuntimeException: %s", cstr.getStr() );
172             jni_env->ThrowNew( c, cstr.getStr() );
173         }
174     }
175     catch (Exception & exc)
176     {
177         jclass c = jni_env->FindClass( "com/sun/star/uno/Exception" );
178         if (0 != c)
179         {
180             OString cstr( ::rtl::OUStringToOString(
181                               exc.Message, RTL_TEXTENCODING_JAVA_UTF8 ) );
182             OSL_TRACE( __FILE__": forwarding Exception: %s", cstr.getStr() );
183             jni_env->ThrowNew( c, cstr.getStr() );
184         }
185     }
186 
187     return 0;
188 }
189 
190