xref: /trunk/main/jvmaccess/source/classpath.cxx (revision 181421139242694b309751fb666406eddc203c50) !
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 #include "sal/config.h"
25 
26 #include "jvmaccess/classpath.hxx"
27 
28 #include <vector>
29 
30 #include "com/sun/star/lang/IllegalArgumentException.hpp"
31 #include "com/sun/star/uno/Any.hxx"
32 #include "com/sun/star/uno/Reference.hxx"
33 #include "com/sun/star/uno/RuntimeException.hpp"
34 #include "com/sun/star/uno/XComponentContext.hpp"
35 #include "com/sun/star/uno/XInterface.hpp"
36 #include "com/sun/star/uri/UriReferenceFactory.hpp"
37 #include "com/sun/star/uri/XVndSunStarExpandUrlReference.hpp"
38 #include "com/sun/star/util/XMacroExpander.hpp"
39 #include "osl/diagnose.h"
40 #include "rtl/ustring.hxx"
41 #include "sal/types.h"
42 
43 #if defined SOLAR_JAVA
44 #include "jni.h"
45 #endif
46 
47 namespace {
48 
49 namespace css = ::com::sun::star;
50 
51 #if defined SOLAR_JAVA
52 // URL schemes that resolve to the local file system or the running JVM image,
53 // optionally wrapped in a jar: URL.
54 //
55 // com.sun.star.comp.sdbc.Tools enforces the same allow-list on the Java side;
56 // keep the two in sync.
isLocalClassPathUrl(::rtl::OUString const & url)57 bool isLocalClassPathUrl(::rtl::OUString const & url)
58 {
59     return url.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("file:"))
60         || url.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("jrt:"))
61         || url.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("jmod:"))
62         || url.matchIgnoreAsciiCaseAsciiL(
63                RTL_CONSTASCII_STRINGPARAM("jar:file:"))
64         || url.matchIgnoreAsciiCaseAsciiL(
65                RTL_CONSTASCII_STRINGPARAM("jar:jrt:"))
66         || url.matchIgnoreAsciiCaseAsciiL(
67                RTL_CONSTASCII_STRINGPARAM("jar:jmod:"));
68 }
69 #endif
70 
71 }
72 
doTranslateToUrls(css::uno::Reference<css::uno::XComponentContext> const & context,void * environment,::rtl::OUString const & classPath)73 void * ::jvmaccess::ClassPath::doTranslateToUrls(
74     css::uno::Reference< css::uno::XComponentContext > const & context,
75     void * environment, ::rtl::OUString const & classPath)
76 {
77     OSL_ASSERT(context.is() && environment != 0);
78 #if defined SOLAR_JAVA
79     ::JNIEnv * const env = static_cast< ::JNIEnv * >(environment);
80     jclass classUrl(env->FindClass("java/net/URL"));
81     if (classUrl == 0) {
82         return 0;
83     }
84     jmethodID ctorUrl(
85         env->GetMethodID(classUrl, "<init>", "(Ljava/lang/String;)V"));
86     if (ctorUrl == 0) {
87         return 0;
88     }
89     ::std::vector< jobject > urls;
90     for (::sal_Int32 i = 0; i != -1;) {
91         ::rtl::OUString url(classPath.getToken(0, ' ', i));
92         if (url.getLength() != 0) {
93             css::uno::Reference< css::uri::XVndSunStarExpandUrlReference >
94                 expUrl(
95                     css::uri::UriReferenceFactory::create(context)->parse(url),
96                     css::uno::UNO_QUERY);
97             if (expUrl.is()) {
98                 css::uno::Reference< css::util::XMacroExpander > expander(
99                     context->getValueByName(
100                         ::rtl::OUString(
101                             RTL_CONSTASCII_USTRINGPARAM(
102                                 "/singletons/"
103                                 "com.sun.star.util.theMacroExpander"))),
104                     css::uno::UNO_QUERY_THROW);
105                 try {
106                     url = expUrl->expand(expander);
107                 } catch (css::lang::IllegalArgumentException & e) {
108                     throw css::uno::RuntimeException(
109                         (::rtl::OUString(
110                             RTL_CONSTASCII_USTRINGPARAM(
111                                 "com.sun.star.lang.IllegalArgumentException: "))
112                          + e.Message),
113                         css::uno::Reference< css::uno::XInterface >());
114                 }
115             }
116             // Add only local entries; a non-local one is logged and skipped.
117             if (!isLocalClassPathUrl(url))
118             {
119                 OSL_TRACE(
120                     "jvmaccess::ClassPath: skipping non-local class path"
121                     " entry: %s",
122                     ::rtl::OUStringToOString(
123                         url, RTL_TEXTENCODING_ASCII_US).getStr());
124                 continue;
125             }
126             jvalue arg;
127             arg.l = env->NewString(
128                 static_cast< jchar const * >(url.getStr()),
129                 static_cast< jsize >(url.getLength()));
130             if (arg.l == 0) {
131                 return 0;
132             }
133             jobject o(env->NewObjectA(classUrl, ctorUrl, &arg));
134             if (o == 0) {
135                 return 0;
136             }
137             urls.push_back(o);
138         }
139     }
140     jobjectArray result = env->NewObjectArray(
141         static_cast< jsize >(urls.size()), classUrl, 0);
142         // static_cast is ok, as each element of urls occupied at least one
143         // character of the ::rtl::OUString classPath
144     if (result == 0) {
145         return 0;
146     }
147     jsize idx = 0;
148     for (std::vector< jobject >::iterator i(urls.begin()); i != urls.end(); ++i)
149     {
150         env->SetObjectArrayElement(result, idx++, *i);
151     }
152     return result;
153 #else
154     return 0;
155 #endif
156 }
157 
doLoadClass(css::uno::Reference<css::uno::XComponentContext> const & context,void * environment,::rtl::OUString const & classPath,::rtl::OUString const & name)158 void * ::jvmaccess::ClassPath::doLoadClass(
159     css::uno::Reference< css::uno::XComponentContext > const & context,
160     void * environment, ::rtl::OUString const & classPath,
161     ::rtl::OUString const & name)
162 {
163     OSL_ASSERT(context.is() && environment != 0);
164 #if defined SOLAR_JAVA
165     ::JNIEnv * const env = static_cast< ::JNIEnv * >(environment);
166     jclass classLoader(env->FindClass("java/net/URLClassLoader"));
167     if (classLoader == 0) {
168         return 0;
169     }
170     jmethodID ctorLoader(
171         env->GetMethodID(classLoader, "<init>", "([Ljava/net/URL;)V"));
172     if (ctorLoader == 0) {
173         return 0;
174     }
175     jvalue arg;
176     arg.l = translateToUrls(context, env, classPath);
177     if (arg.l == 0) {
178         return 0;
179     }
180     jobject cl = env->NewObjectA(classLoader, ctorLoader, &arg);
181     if (cl == 0) {
182         return 0;
183     }
184     jmethodID methLoadClass(
185         env->GetMethodID(
186             classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"));
187     if (methLoadClass == 0) {
188         return 0;
189     }
190     arg.l = env->NewString(
191         static_cast< jchar const * >(name.getStr()),
192         static_cast< jsize >(name.getLength()));
193     if (arg.l == 0) {
194         return 0;
195     }
196     return env->CallObjectMethodA(cl, methLoadClass, &arg);
197 #else
198     return 0;
199 #endif
200 }
201