1 /* 2 * This file is part of the LibreOffice project. 3 * 4 * This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 7 * 8 * This file incorporates work covered by the following license notice: 9 * 10 * Licensed to the Apache Software Foundation (ASF) under one or more 11 * contributor license agreements. See the NOTICE file distributed 12 * with this work for additional information regarding copyright 13 * ownership. The ASF licenses this file to you under the Apache 14 * License, Version 2.0 (the "License"); you may not use this file 15 * except in compliance with the License. You may obtain a copy of 16 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 17 */ 18 package com.sun.star.script.framework.provider.java; 19 20 import com.sun.star.comp.loader.FactoryHelper; 21 22 import com.sun.star.document.XScriptInvocationContext; 23 24 import com.sun.star.frame.XModel; 25 26 import com.sun.star.lang.XMultiComponentFactory; 27 import com.sun.star.lang.XMultiServiceFactory; 28 import com.sun.star.lang.XSingleServiceFactory; 29 30 import com.sun.star.registry.XRegistryKey; 31 32 import com.sun.star.script.framework.container.ScriptMetaData; 33 import com.sun.star.script.framework.log.LogUtils; 34 import com.sun.star.script.framework.provider.ClassLoaderFactory; 35 import com.sun.star.script.framework.provider.ScriptContext; 36 import com.sun.star.script.framework.provider.ScriptEditor; 37 import com.sun.star.script.framework.provider.ScriptProvider; 38 import com.sun.star.script.provider.ScriptExceptionRaisedException; 39 import com.sun.star.script.provider.ScriptFrameworkErrorException; 40 import com.sun.star.script.provider.ScriptFrameworkErrorType; 41 import com.sun.star.script.provider.XScript; 42 import com.sun.star.script.provider.XScriptContext; 43 44 import com.sun.star.uno.Any; 45 import com.sun.star.uno.Type; 46 import com.sun.star.uno.XComponentContext; 47 48 import java.io.IOException; 49 import java.net.URLClassLoader; 50 import java.util.ArrayList; 51 52 public class ScriptProviderForJava { 53 54 public static class _ScriptProviderForJava extends ScriptProvider { 55 56 private final Resolver m_resolutionPolicy = new StrictResolver(); 57 _ScriptProviderForJava(XComponentContext ctx)58 public _ScriptProviderForJava(XComponentContext ctx) { 59 super(ctx, "Java"); 60 } 61 62 @Override getScript( String scriptURI)63 public XScript getScript(/*IN*/String scriptURI) throws 64 com.sun.star.uno.RuntimeException, ScriptFrameworkErrorException { 65 66 ScriptMetaData scriptData = getScriptData(scriptURI); 67 68 try { 69 70 ScriptImpl script = 71 new ScriptImpl(m_xContext, m_resolutionPolicy, scriptData, m_xModel, 72 m_xInvocContext); 73 74 return script; 75 } catch (com.sun.star.uno.RuntimeException re) { 76 ScriptFrameworkErrorException e2 = new ScriptFrameworkErrorException( 77 "Failed to create script object: " + re, null, 78 scriptData.getLanguageName(), language, 79 ScriptFrameworkErrorType.UNKNOWN); 80 e2.initCause(re); 81 throw e2; 82 } 83 } 84 85 @Override hasScriptEditor()86 public boolean hasScriptEditor() { 87 return false; 88 } 89 90 @Override getScriptEditor()91 public ScriptEditor getScriptEditor() { 92 return null; 93 } 94 } 95 96 /** 97 * Returns a factory for creating the service. 98 * This method is called by the <code>JavaLoader</code> 99 * <p> 100 * 101 * @param implName the name of the implementation for which a service is desired 102 * @param multiFactory the service manager to be used if needed 103 * @param regKey the registryKey 104 * @return returns a <code>XSingleServiceFactory</code> for creating 105 * the component 106 * @see com.sun.star.comp.loader.JavaLoader 107 */ __getServiceFactory( String implName, XMultiServiceFactory multiFactory, XRegistryKey regKey)108 public static XSingleServiceFactory __getServiceFactory( 109 String implName, XMultiServiceFactory multiFactory, XRegistryKey regKey) { 110 111 XSingleServiceFactory xSingleServiceFactory = null; 112 113 if (implName.equals( 114 ScriptProviderForJava._ScriptProviderForJava.class.getName())) { 115 116 xSingleServiceFactory = 117 FactoryHelper.getServiceFactory( 118 ScriptProviderForJava._ScriptProviderForJava.class, 119 "com.sun.star.script.provider.ScriptProviderForJava", 120 multiFactory, regKey); 121 122 } 123 124 return xSingleServiceFactory; 125 } 126 } 127 128 class ScriptImpl implements XScript { 129 130 private final ScriptMetaData metaData; 131 private final XComponentContext m_xContext; 132 private final XModel m_xModel; 133 private final XScriptInvocationContext m_xInvocContext; 134 private XMultiComponentFactory m_xMultiComponentFactory; 135 private final Resolver m_resolutionPolicy; 136 ScriptImpl(XComponentContext ctx, Resolver resolver, ScriptMetaData metaData, XModel xModel, XScriptInvocationContext xInvocContext)137 ScriptImpl(XComponentContext ctx, Resolver resolver, ScriptMetaData metaData, 138 XModel xModel, XScriptInvocationContext xInvocContext) throws 139 com.sun.star.uno.RuntimeException { 140 141 this.metaData = metaData; 142 this.m_xContext = ctx; 143 this.m_xModel = xModel; 144 this.m_xInvocContext = xInvocContext; 145 this.m_resolutionPolicy = resolver; 146 147 try { 148 this.m_xMultiComponentFactory = m_xContext.getServiceManager(); 149 } catch (Exception e) { 150 LogUtils.DEBUG(LogUtils.getTrace(e)); 151 throw new com.sun.star.uno.RuntimeException( 152 e, "Error constructing ScriptProvider: " + e); 153 } 154 155 LogUtils.DEBUG("ScriptImpl [java] script data = " + metaData); 156 } 157 158 /** 159 * Invoke 160 * 161 * 162 * @param params All parameters; pure, out params are undefined in 163 * sequence, i.e., the value has to be ignored by the callee 164 * @param aOutParamIndex Out indices 165 * @param aOutParam Out parameters 166 * @return The value returned from the function being invoked 167 * @throws IllegalArgumentException If there is no matching script name 168 * @throws com.sun.star.reflection.InvocationTargetException If the running script throws an exception 169 * this information is captured and rethrown as this exception type. 170 */ invoke( Object[] params, short[][] aOutParamIndex, Object[][] aOutParam)171 public Object invoke( 172 /*IN*/Object[] params, 173 /*OUT*/short[][] aOutParamIndex, 174 /*OUT*/Object[][] aOutParam) throws 175 ScriptFrameworkErrorException, 176 com.sun.star.reflection.InvocationTargetException { 177 178 LogUtils.DEBUG("** ScriptProviderForJava::invoke: Starting..."); 179 180 // Initialise the out parameters - not used at the moment 181 aOutParamIndex[0] = new short[0]; 182 aOutParam[0] = new Object[0]; 183 184 ScriptDescriptor scriptDesc = 185 new ScriptDescriptor(metaData.getLanguageName()); 186 187 Object[] invocationArgs = null; 188 ScriptProxy script = null; 189 190 LogUtils.DEBUG("Classloader starting..."); 191 192 try (URLClassLoader scriptLoader = ClassLoaderFactory.getURLClassLoader(metaData)) { 193 LogUtils.DEBUG("Classloader finished..."); 194 195 ArrayList<Object> invocationArgList = new ArrayList<Object>(); 196 197 LogUtils.DEBUG("Parameter Mapping..."); 198 199 // Setup Context Object 200 XScriptContext xSc = 201 ScriptContext.createContext(m_xModel, m_xInvocContext, 202 m_xContext, m_xMultiComponentFactory); 203 204 scriptDesc.addArgumentType(XScriptContext.class); 205 invocationArgList.add(xSc); 206 207 for (int i = 0; i < params.length; i++) { 208 scriptDesc.addArgumentType(params[ i ].getClass()); 209 invocationArgList.add(params[ i ]); 210 } 211 212 if (!invocationArgList.isEmpty()) { 213 invocationArgs = invocationArgList.toArray(); 214 } 215 216 LogUtils.DEBUG("ScriptProxy starting... "); 217 218 try { 219 220 String className = metaData.getLanguageName().substring(0, 221 metaData.getLanguageName().lastIndexOf('.')); 222 223 LogUtils.DEBUG("About to load Class " + className + " starting... "); 224 225 long start = new java.util.Date().getTime(); 226 Class<?> c = scriptLoader.loadClass(className); 227 long end = new java.util.Date().getTime(); 228 229 LogUtils.DEBUG("loadClass took: " + (end - start) + "milliseconds"); 230 231 try { 232 LogUtils.DEBUG("class loaded ... "); 233 script = m_resolutionPolicy.getProxy(scriptDesc, c); 234 LogUtils.DEBUG("script resolved ... "); 235 } catch (NoSuchMethodException e) { 236 // Framework error 237 ScriptFrameworkErrorException e2 = new ScriptFrameworkErrorException( 238 e.toString(), null, metaData.getLanguageName(), 239 metaData.getLanguage(), ScriptFrameworkErrorType.NO_SUCH_SCRIPT); 240 e2.initCause(e); 241 throw e2; 242 } 243 } catch (ClassNotFoundException e) { 244 // Framework error 245 ScriptFrameworkErrorException e2 = new ScriptFrameworkErrorException( 246 e.toString(), null, metaData.getLanguageName(), 247 metaData.getLanguage(), ScriptFrameworkErrorType.NO_SUCH_SCRIPT); 248 e2.initCause(e); 249 throw e2; 250 } 251 } catch (IOException e) { 252 // Framework error 253 ScriptFrameworkErrorException e2 = new ScriptFrameworkErrorException( 254 e.toString(), null, metaData.getLanguageName(), metaData.getLanguage(), 255 ScriptFrameworkErrorType.NO_SUCH_SCRIPT); 256 e2.initCause(e); 257 throw e2; 258 } 259 260 LogUtils.DEBUG("Starting Invoke on Proxy ..."); 261 Object result = null; 262 263 try { 264 long start = new java.util.Date().getTime(); 265 result = script.invoke(invocationArgs); 266 long end = new java.util.Date().getTime(); 267 LogUtils.DEBUG("invoke took: " + (end - start) + "milliseconds"); 268 } catch (java.lang.IllegalArgumentException iae) { 269 ScriptFrameworkErrorException e2 = new ScriptFrameworkErrorException( 270 iae.getMessage(), null, metaData.getLanguageName(), 271 metaData.getLanguage(), ScriptFrameworkErrorType.UNKNOWN); 272 e2.initCause(iae); 273 throw e2; 274 } catch (java.lang.IllegalAccessException ia) { 275 ScriptFrameworkErrorException e2 = new ScriptFrameworkErrorException( 276 ia.toString(), null, metaData.getLanguageName(), 277 metaData.getLanguage(), ScriptFrameworkErrorType.UNKNOWN); 278 e2.initCause(ia); 279 throw e2; 280 } catch (java.lang.reflect.InvocationTargetException ite) { 281 Throwable targetException = ite.getTargetException(); 282 283 ScriptExceptionRaisedException se = 284 new ScriptExceptionRaisedException(targetException.toString()); 285 286 se.lineNum = -1; 287 se.scriptName = metaData.getLanguageName(); 288 se.language = "Java"; 289 se.exceptionType = targetException.getClass().getName(); 290 291 throw new com.sun.star.reflection.InvocationTargetException( 292 "Scripting Framework error executing script ", null, se); 293 294 } catch (Exception unknown) { 295 ScriptExceptionRaisedException se = 296 new ScriptExceptionRaisedException(unknown.toString()); 297 se.lineNum = -1; 298 se.scriptName = metaData.getLanguageName(); 299 se.language = "Java"; 300 se.exceptionType = unknown.getClass().getName(); 301 throw new com.sun.star.reflection.InvocationTargetException( 302 "Scripting Framework error executing script ", null, se); 303 } 304 305 if (result == null) { 306 LogUtils.DEBUG("Got Nothing Back"); 307 // in the case where there is no return type 308 Any voidAny = new Any(new Type(), null); 309 result = voidAny; 310 } else { 311 LogUtils.DEBUG("Got object " + result); 312 } 313 314 return result; 315 } 316 }