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. 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 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 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