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