1cd519653SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3cd519653SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4cd519653SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5cd519653SAndrew Rist  * distributed with this work for additional information
6cd519653SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7cd519653SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8cd519653SAndrew Rist  * "License"); you may not use this file except in compliance
9cd519653SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cd519653SAndrew Rist  *
11cd519653SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cd519653SAndrew Rist  *
13cd519653SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14cd519653SAndrew Rist  * software distributed under the License is distributed on an
15cd519653SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16cd519653SAndrew Rist  * KIND, either express or implied.  See the License for the
17cd519653SAndrew Rist  * specific language governing permissions and limitations
18cd519653SAndrew Rist  * under the License.
19cd519653SAndrew Rist  *
20cd519653SAndrew Rist  *************************************************************/
21cd519653SAndrew Rist 
22cd519653SAndrew Rist 
23cdf0e10cSrcweir package com.sun.star.script.framework.provider.javascript;
24cdf0e10cSrcweir 
25cdf0e10cSrcweir import com.sun.star.uno.XComponentContext;
26cdf0e10cSrcweir import com.sun.star.lang.XMultiComponentFactory;
27cdf0e10cSrcweir import com.sun.star.lang.XMultiServiceFactory;
28cdf0e10cSrcweir import com.sun.star.lang.XSingleServiceFactory;
29cdf0e10cSrcweir import com.sun.star.frame.XModel;
30cdf0e10cSrcweir import com.sun.star.registry.XRegistryKey;
31cdf0e10cSrcweir import com.sun.star.comp.loader.FactoryHelper;
32cdf0e10cSrcweir 
33cdf0e10cSrcweir import com.sun.star.document.XScriptInvocationContext;
34cdf0e10cSrcweir import com.sun.star.reflection.InvocationTargetException;
35cdf0e10cSrcweir 
36cdf0e10cSrcweir import java.net.URL;
37cdf0e10cSrcweir 
38cdf0e10cSrcweir import com.sun.star.script.provider.XScript;
39cdf0e10cSrcweir 
40cdf0e10cSrcweir import com.sun.star.script.provider.ScriptExceptionRaisedException;
41cdf0e10cSrcweir import com.sun.star.script.provider.ScriptFrameworkErrorException;
42cdf0e10cSrcweir import com.sun.star.script.provider.ScriptFrameworkErrorType;
43cdf0e10cSrcweir 
44cdf0e10cSrcweir import com.sun.star.script.framework.log.LogUtils;
45cdf0e10cSrcweir import com.sun.star.script.framework.provider.ScriptContext;
46cdf0e10cSrcweir import com.sun.star.script.framework.provider.ClassLoaderFactory;
47cdf0e10cSrcweir import com.sun.star.script.framework.provider.ScriptProvider;
48cdf0e10cSrcweir import com.sun.star.script.framework.provider.ScriptEditor;
49cdf0e10cSrcweir import com.sun.star.script.framework.container.ScriptMetaData;
50cdf0e10cSrcweir 
51cdf0e10cSrcweir import org.mozilla.javascript.Context;
52cdf0e10cSrcweir import org.mozilla.javascript.ImporterTopLevel;
53cdf0e10cSrcweir import org.mozilla.javascript.Scriptable;
54cdf0e10cSrcweir import org.mozilla.javascript.JavaScriptException;
55cdf0e10cSrcweir 
56cdf0e10cSrcweir public class ScriptProviderForJavaScript
57cdf0e10cSrcweir {
58cdf0e10cSrcweir     public static class _ScriptProviderForJavaScript extends ScriptProvider
59cdf0e10cSrcweir     {
_ScriptProviderForJavaScript(XComponentContext ctx)60cdf0e10cSrcweir         public _ScriptProviderForJavaScript(XComponentContext ctx)
61cdf0e10cSrcweir         {
62cdf0e10cSrcweir             super(ctx, "JavaScript");
63cdf0e10cSrcweir         }
64cdf0e10cSrcweir 
getScript( String scriptURI )65cdf0e10cSrcweir         public XScript getScript( /*IN*/String scriptURI )
66cdf0e10cSrcweir             throws com.sun.star.uno.RuntimeException,
67cdf0e10cSrcweir                    ScriptFrameworkErrorException
68cdf0e10cSrcweir         {
69cdf0e10cSrcweir             ScriptMetaData scriptData = null;
70cdf0e10cSrcweir             try
71cdf0e10cSrcweir             {
72cdf0e10cSrcweir                 scriptData = getScriptData( scriptURI );
73cdf0e10cSrcweir                 ScriptImpl script = new ScriptImpl( m_xContext, scriptData, m_xModel, m_xInvocContext );
74cdf0e10cSrcweir                 return script;
75cdf0e10cSrcweir             }
76cdf0e10cSrcweir             catch ( com.sun.star.uno.RuntimeException re )
77cdf0e10cSrcweir             {
78cdf0e10cSrcweir                 throw new ScriptFrameworkErrorException( "Failed to create script object: " + re.getMessage(),
79cdf0e10cSrcweir                     null, scriptData.getLanguageName(), language, ScriptFrameworkErrorType.UNKNOWN );
80cdf0e10cSrcweir             }
81cdf0e10cSrcweir         }
82cdf0e10cSrcweir 
hasScriptEditor()83cdf0e10cSrcweir         public boolean hasScriptEditor()
84cdf0e10cSrcweir         {
85cdf0e10cSrcweir             return true;
86cdf0e10cSrcweir         }
87cdf0e10cSrcweir 
getScriptEditor()88cdf0e10cSrcweir         public ScriptEditor getScriptEditor()
89cdf0e10cSrcweir         {
90cdf0e10cSrcweir             return ScriptEditorForJavaScript.getEditor();
91cdf0e10cSrcweir         }
92cdf0e10cSrcweir     }
93cdf0e10cSrcweir 
94cdf0e10cSrcweir     /**
95cdf0e10cSrcweir      * Returns a factory for creating the service.
96cdf0e10cSrcweir      * This method is called by the <code>JavaLoader</code>
97cdf0e10cSrcweir      * <p>
98cdf0e10cSrcweir      *
99cdf0e10cSrcweir      * @param  implName      the name of the implementation for which a service is desired
100cdf0e10cSrcweir      * @param  multiFactory  the service manager to be used if needed
101cdf0e10cSrcweir      * @param  regKey        the registryKey
102cdf0e10cSrcweir      * @return               returns a <code>XSingleServiceFactory</code> for creating
103cdf0e10cSrcweir      *                          the component
104cdf0e10cSrcweir      * @see                  com.sun.star.comp.loader.JavaLoader
105cdf0e10cSrcweir      */
__getServiceFactory( String implName, XMultiServiceFactory multiFactory, XRegistryKey regKey )106cdf0e10cSrcweir     public static XSingleServiceFactory __getServiceFactory( String implName,
107cdf0e10cSrcweir             XMultiServiceFactory multiFactory,
108cdf0e10cSrcweir             XRegistryKey regKey )
109cdf0e10cSrcweir     {
110cdf0e10cSrcweir         XSingleServiceFactory xSingleServiceFactory = null;
111cdf0e10cSrcweir 
112cdf0e10cSrcweir         if ( implName.equals( ScriptProviderForJavaScript._ScriptProviderForJavaScript.class.getName() ) )
113cdf0e10cSrcweir         {
114cdf0e10cSrcweir             xSingleServiceFactory = FactoryHelper.getServiceFactory(
115cdf0e10cSrcweir                 ScriptProviderForJavaScript._ScriptProviderForJavaScript.class,
116cdf0e10cSrcweir                 "com.sun.star.script.provider.ScriptProviderForJavaScript",
117cdf0e10cSrcweir                 multiFactory,
118cdf0e10cSrcweir                 regKey );
119cdf0e10cSrcweir         }
120cdf0e10cSrcweir 
121cdf0e10cSrcweir         return xSingleServiceFactory;
122cdf0e10cSrcweir     }
123cdf0e10cSrcweir }
124cdf0e10cSrcweir class ScriptImpl implements XScript
125cdf0e10cSrcweir {
126cdf0e10cSrcweir     private ScriptMetaData metaData;
127cdf0e10cSrcweir     private XComponentContext m_xContext;
128cdf0e10cSrcweir     private XMultiComponentFactory m_xMultiComponentFactory;
129cdf0e10cSrcweir     private XModel m_xModel;
130cdf0e10cSrcweir     private XScriptInvocationContext m_xInvocContext;
131cdf0e10cSrcweir 
ScriptImpl( XComponentContext ctx, ScriptMetaData metaData, XModel xModel, XScriptInvocationContext xInvocContext )132cdf0e10cSrcweir     ScriptImpl( XComponentContext ctx, ScriptMetaData metaData, XModel xModel, XScriptInvocationContext xInvocContext ) throws com.sun.star.uno.RuntimeException
133cdf0e10cSrcweir     {
134cdf0e10cSrcweir         this.metaData = metaData;
135cdf0e10cSrcweir         this.m_xContext = ctx;
136cdf0e10cSrcweir         this.m_xModel = xModel;
137cdf0e10cSrcweir         this.m_xInvocContext = xInvocContext;
138cdf0e10cSrcweir         try
139cdf0e10cSrcweir         {
140cdf0e10cSrcweir             this.m_xMultiComponentFactory = m_xContext.getServiceManager();
141cdf0e10cSrcweir         }
142cdf0e10cSrcweir         catch ( Exception e )
143cdf0e10cSrcweir         {
144cdf0e10cSrcweir             LogUtils.DEBUG( LogUtils.getTrace( e ) );
145cdf0e10cSrcweir             throw new com.sun.star.uno.RuntimeException(
146cdf0e10cSrcweir                 "Error constructing  ScriptImpl: [javascript]");
147cdf0e10cSrcweir         }
148cdf0e10cSrcweir         LogUtils.DEBUG("ScriptImpl [javascript] script data = " + metaData );
149cdf0e10cSrcweir     }
150cdf0e10cSrcweir 
151cdf0e10cSrcweir         /**
152cdf0e10cSrcweir          *  The invoke method of the ScriptProviderForJavaScript runs the
153cdf0e10cSrcweir          *  JavaScript script specified in the URI
154cdf0e10cSrcweir          *
155cdf0e10cSrcweir          *
156cdf0e10cSrcweir          *
157e6b649b5SPedro Giffuni          * @param params            All parameters; pure, out params are
158cdf0e10cSrcweir          *                          undefined in sequence, i.e., the value
159cdf0e10cSrcweir          *                          has to be ignored by the callee
160cdf0e10cSrcweir          *
161cdf0e10cSrcweir          * @param aOutParamIndex    Out indices
162cdf0e10cSrcweir          *
163cdf0e10cSrcweir          * @param aOutParam         Out parameters
164cdf0e10cSrcweir          *
165cdf0e10cSrcweir          * @returns                 The value returned from the function
166cdf0e10cSrcweir          *                          being invoked
167cdf0e10cSrcweir          *
168cdf0e10cSrcweir          * @throws ScriptFrameworkErrorException If there is no matching script name
169cdf0e10cSrcweir          *
170cdf0e10cSrcweir          *
171cdf0e10cSrcweir          * @throws InvocationTargetException If the running script throws
172cdf0e10cSrcweir          *                                   an exception this information
173cdf0e10cSrcweir          *                                   is captured and rethrown as
174cdf0e10cSrcweir          *                                   ScriptErrorRaisedException or
175cdf0e10cSrcweir          *                                   ScriptExceptionRaisedException
176cdf0e10cSrcweir          */
177cdf0e10cSrcweir 
invoke( Object[] params, short[][] aOutParamIndex, Object[][] aOutParam )178cdf0e10cSrcweir         public Object invoke(
179cdf0e10cSrcweir                                /*IN*/Object[]  params,
180cdf0e10cSrcweir                                /*OUT*/short[][]  aOutParamIndex,
181cdf0e10cSrcweir                                /*OUT*/Object[][]  aOutParam )
182cdf0e10cSrcweir 
183cdf0e10cSrcweir         throws ScriptFrameworkErrorException, InvocationTargetException
184cdf0e10cSrcweir         {
185*86e1cf34SPedro Giffuni             // Initialise the out parameters - not used at the moment
186cdf0e10cSrcweir             aOutParamIndex[0] = new short[0];
187cdf0e10cSrcweir             aOutParam[0] = new Object[0];
188cdf0e10cSrcweir 
189cdf0e10cSrcweir 
190cdf0e10cSrcweir 
191cdf0e10cSrcweir             ClassLoader cl = null;
192cdf0e10cSrcweir             URL sourceUrl = null;
193cdf0e10cSrcweir             try {
194cdf0e10cSrcweir                 cl = ClassLoaderFactory.getURLClassLoader( metaData );
195cdf0e10cSrcweir                 sourceUrl = metaData.getSourceURL();
196cdf0e10cSrcweir             }
197cdf0e10cSrcweir             catch ( java.net.MalformedURLException mfu )
198cdf0e10cSrcweir             {
199cdf0e10cSrcweir                 throw new ScriptFrameworkErrorException(
200cdf0e10cSrcweir                     mfu.getMessage(), null,
201cdf0e10cSrcweir                     metaData.getLanguageName(), metaData.getLanguage(),
202cdf0e10cSrcweir                     ScriptFrameworkErrorType.MALFORMED_URL );
203cdf0e10cSrcweir             }
204cdf0e10cSrcweir             catch ( com.sun.star.script.framework.provider.NoSuitableClassLoaderException nsc )
205cdf0e10cSrcweir             {
206cdf0e10cSrcweir                 // Framework error
207cdf0e10cSrcweir                 throw new ScriptFrameworkErrorException(
208cdf0e10cSrcweir                     nsc.getMessage(), null,
209cdf0e10cSrcweir                     metaData.getLanguageName(), metaData.getLanguage(),
210cdf0e10cSrcweir                     ScriptFrameworkErrorType.UNKNOWN );
211cdf0e10cSrcweir             }
212cdf0e10cSrcweir             Context ctxt = null;
213cdf0e10cSrcweir 
214cdf0e10cSrcweir             try
215cdf0e10cSrcweir             {
216cdf0e10cSrcweir                 String editorURL = sourceUrl.toString();
217cdf0e10cSrcweir                 Object result = null;
218cdf0e10cSrcweir                 String source = null;
219cdf0e10cSrcweir                 ScriptEditorForJavaScript editor =
220cdf0e10cSrcweir                     ScriptEditorForJavaScript.getEditor(
221cdf0e10cSrcweir                         metaData.getSourceURL() );
222cdf0e10cSrcweir 
223cdf0e10cSrcweir                 if (editor != null)
224cdf0e10cSrcweir                 {
225cdf0e10cSrcweir                     editorURL = editor.getURL();
226cdf0e10cSrcweir                     result = editor.execute();
227cdf0e10cSrcweir                     if ( result != null  &&
228cdf0e10cSrcweir                          result.getClass().getName().equals( "org.mozilla.javascript.Undefined" ) )
229cdf0e10cSrcweir                     {
230cdf0e10cSrcweir                         // Always return a string
231cdf0e10cSrcweir                         // TODO revisit
232cdf0e10cSrcweir                         return Context.toString( result );
233cdf0e10cSrcweir                     }
234cdf0e10cSrcweir 
235cdf0e10cSrcweir                 }
236cdf0e10cSrcweir 
237cdf0e10cSrcweir                 if (editor != null && editor.isModified() == true)
238cdf0e10cSrcweir                 {
239cdf0e10cSrcweir                     LogUtils.DEBUG("GOT A MODIFIED SOURCE");
240cdf0e10cSrcweir                     source = editor.getText();
241cdf0e10cSrcweir                 }
242cdf0e10cSrcweir                 else
243cdf0e10cSrcweir                 {
244cdf0e10cSrcweir                     metaData.loadSource();
245cdf0e10cSrcweir                     source =  metaData.getSource();
246cdf0e10cSrcweir 
247cdf0e10cSrcweir                 }
248cdf0e10cSrcweir 
249cdf0e10cSrcweir                 if ( source == null || source.length() == 0 ) {
250cdf0e10cSrcweir                     throw new ScriptFrameworkErrorException(
251cdf0e10cSrcweir                         "Failed to read source data for script", null,
252cdf0e10cSrcweir                         metaData.getLanguageName(), metaData.getLanguage(),
253cdf0e10cSrcweir                         ScriptFrameworkErrorType.UNKNOWN );
254cdf0e10cSrcweir                 }
255cdf0e10cSrcweir 
256cdf0e10cSrcweir                 /* Set the context ClassLoader on the current thread to
257cdf0e10cSrcweir                    be our custom ClassLoader. This is the suggested method
258cdf0e10cSrcweir                    for setting up a ClassLoader to be used by the Rhino
259cdf0e10cSrcweir                    interpreter
260cdf0e10cSrcweir                  */
261cdf0e10cSrcweir                 if (cl != null) {
262cdf0e10cSrcweir                     Thread.currentThread().setContextClassLoader(cl);
263cdf0e10cSrcweir                 }
264cdf0e10cSrcweir 
265cdf0e10cSrcweir                 // Initialize a Rhino Context object
266cdf0e10cSrcweir                 ctxt = Context.enter();
26775252d1bSAndre Fischer                 ctxt.setLanguageVersion(Context.VERSION_1_8);
26875252d1bSAndre Fischer                 ctxt.setOptimizationLevel(9);
269cdf0e10cSrcweir 
270cdf0e10cSrcweir                 /* The ImporterTopLevel ensures that importClass and
271cdf0e10cSrcweir                    importPackage statements work in Javascript scripts
272cdf0e10cSrcweir                    Make the XScriptContext available as a global variable
273cdf0e10cSrcweir                    to the script
274cdf0e10cSrcweir                  */
275cdf0e10cSrcweir                 ImporterTopLevel scope = new ImporterTopLevel(ctxt);
276cdf0e10cSrcweir 
277cdf0e10cSrcweir                 Scriptable jsCtxt = Context.toObject(
278cdf0e10cSrcweir                    ScriptContext.createContext(
279cdf0e10cSrcweir                        m_xModel, m_xInvocContext, m_xContext,
280cdf0e10cSrcweir                        m_xMultiComponentFactory), scope);
281cdf0e10cSrcweir                 scope.put("XSCRIPTCONTEXT", scope, jsCtxt);
282cdf0e10cSrcweir 
283cdf0e10cSrcweir                 Scriptable jsArgs = Context.toObject(params, scope);
284cdf0e10cSrcweir                 scope.put("ARGUMENTS", scope, jsArgs);
285cdf0e10cSrcweir 
286cdf0e10cSrcweir                 result = ctxt.evaluateString(scope,
287cdf0e10cSrcweir                         source, "<stdin>", 1, null);
288cdf0e10cSrcweir                 result = ctxt.toString(result);
289cdf0e10cSrcweir 				return result;
290cdf0e10cSrcweir             }
291cdf0e10cSrcweir             catch (JavaScriptException jse) {
292cdf0e10cSrcweir                 LogUtils.DEBUG( "Caught JavaScriptException exception for JavaScript type = " + jse.getClass() );
293cdf0e10cSrcweir                 String message = jse.getMessage();
29475252d1bSAndre Fischer                 int lineNo = jse.lineNumber();
295cdf0e10cSrcweir                 Object wrap = jse.getValue();
296cdf0e10cSrcweir                 LogUtils.DEBUG( "\t message  " + message );
297cdf0e10cSrcweir                 LogUtils.DEBUG( "\t wrapped type " + wrap.getClass() );
298cdf0e10cSrcweir                 LogUtils.DEBUG( "\t wrapped toString  " + wrap.toString() );
299cdf0e10cSrcweir                 ScriptExceptionRaisedException se = new
300cdf0e10cSrcweir                     ScriptExceptionRaisedException( message );
30175252d1bSAndre Fischer                 se.lineNum = lineNo;
302cdf0e10cSrcweir                 se.language = "JavaScript";
303cdf0e10cSrcweir                 se.scriptName = metaData.getLanguageName();
304cdf0e10cSrcweir                 se.exceptionType = wrap.getClass().getName();
305cdf0e10cSrcweir                 se.language = metaData.getLanguage();
306cdf0e10cSrcweir                 LogUtils.DEBUG( "ExceptionRaised exception  "  );
307cdf0e10cSrcweir                 LogUtils.DEBUG( "\t message  " + se.getMessage() );
308cdf0e10cSrcweir                 LogUtils.DEBUG( "\t lineNum  " + se.lineNum );
309cdf0e10cSrcweir                 LogUtils.DEBUG( "\t language  " + se.language );
310cdf0e10cSrcweir                 LogUtils.DEBUG( "\t scriptName  " + se.scriptName );
311cdf0e10cSrcweir                 raiseEditor( se.lineNum );
312cdf0e10cSrcweir                 throw new InvocationTargetException( "JavaScript uncaught exception" + metaData.getLanguageName(), null, se );
313cdf0e10cSrcweir             }
314cdf0e10cSrcweir             catch (Exception ex) {
315cdf0e10cSrcweir                 LogUtils.DEBUG("Caught Exception " + ex );
316cdf0e10cSrcweir                 LogUtils.DEBUG("rethrowing as ScriptFramework error"  );
317cdf0e10cSrcweir                 throw new ScriptFrameworkErrorException(
318cdf0e10cSrcweir                     ex.getMessage(), null,
319cdf0e10cSrcweir                     metaData.getLanguageName(), metaData.getLanguage(),
320cdf0e10cSrcweir                     ScriptFrameworkErrorType.UNKNOWN );
321cdf0e10cSrcweir             }
322cdf0e10cSrcweir             finally {
323cdf0e10cSrcweir                 if ( ctxt != null )
324cdf0e10cSrcweir                 {
325cdf0e10cSrcweir                     Context.exit();
326cdf0e10cSrcweir                 }
327cdf0e10cSrcweir             }
328cdf0e10cSrcweir         }
329cdf0e10cSrcweir 
raiseEditor( int lineNum )330cdf0e10cSrcweir         private void raiseEditor( int lineNum )
331cdf0e10cSrcweir         {
332cdf0e10cSrcweir             ScriptEditorForJavaScript editor = null;
333cdf0e10cSrcweir             try
334cdf0e10cSrcweir             {
335cdf0e10cSrcweir                 URL sourceUrl = metaData.getSourceURL();
336cdf0e10cSrcweir                 editor = ScriptEditorForJavaScript.getEditor( sourceUrl );
337cdf0e10cSrcweir                 if ( editor == null )
338cdf0e10cSrcweir                 {
339cdf0e10cSrcweir                     editor = ScriptEditorForJavaScript.getEditor();
340cdf0e10cSrcweir                     editor.edit(
341cdf0e10cSrcweir                         ScriptContext.createContext(m_xModel, m_xInvocContext,
342cdf0e10cSrcweir                             m_xContext, m_xMultiComponentFactory), metaData );
343cdf0e10cSrcweir                     editor = ScriptEditorForJavaScript.getEditor( sourceUrl );
344cdf0e10cSrcweir                 }
345cdf0e10cSrcweir                 if ( editor != null )
346cdf0e10cSrcweir                 {
347cdf0e10cSrcweir                     System.out.println("** Have raised IDE for JavaScript, calling indicateErrorLine for line " + lineNum );
348cdf0e10cSrcweir                     editor.indicateErrorLine( lineNum );
349cdf0e10cSrcweir                 }
350cdf0e10cSrcweir             }
351cdf0e10cSrcweir             catch( Exception ignore )
352cdf0e10cSrcweir             {
353cdf0e10cSrcweir             }
354cdf0e10cSrcweir         }
355cdf0e10cSrcweir }
356cdf0e10cSrcweir 
357