diff options
Diffstat (limited to 'scripting/java/com/sun/star/script/framework/provider/beanshell')
6 files changed, 1266 insertions, 0 deletions
diff --git a/scripting/java/com/sun/star/script/framework/provider/beanshell/PlainSourceView.java b/scripting/java/com/sun/star/script/framework/provider/beanshell/PlainSourceView.java new file mode 100755 index 000000000000..509da1623f53 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/provider/beanshell/PlainSourceView.java @@ -0,0 +1,247 @@ +/************************************************************************* +* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ +package com.sun.star.script.framework.provider.beanshell; + +import javax.swing.JTextArea; +import javax.swing.JScrollPane; +import javax.swing.JComponent; +import javax.swing.event.DocumentListener; +import javax.swing.event.DocumentEvent; + +import java.awt.Graphics; +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.Dimension; + +public class PlainSourceView extends JScrollPane + implements ScriptSourceView, DocumentListener { + + private ScriptSourceModel model; + private JTextArea ta; + private GlyphGutter gg; + private int linecount; + private boolean isModified = false; + + public PlainSourceView(ScriptSourceModel model) { + this.model = model; + initUI(); + model.setView(this); + } + + public void clear() { + ta.setText(""); + } + + public void update() { + /* Remove ourselves as a DocumentListener while loading the source + so we don't get a storm of DocumentEvents during loading */ + ta.getDocument().removeDocumentListener(this); + + if (isModified == false) + { + int pos = ta.getCaretPosition(); + ta.setText(model.getText()); + try { + ta.setCaretPosition(pos); + } + catch (IllegalArgumentException iae) { + // do nothing and allow JTextArea to set it's own position + } + } + + // scroll to currentPosition of the model + try { + int line = ta.getLineStartOffset(model.getCurrentPosition()); + Rectangle rect = ta.modelToView(line); + ta.scrollRectToVisible(rect); + } + catch (Exception e) { + // couldn't scroll to line, do nothing + } + + gg.repaint(); + + // Add back the listener + ta.getDocument().addDocumentListener(this); + } + + public boolean isModified() { + return isModified; + } + + public void setModified(boolean value) { + isModified = value; + } + + private void initUI() { + ta = new JTextArea(); + ta.setRows(15); + ta.setColumns(40); + ta.setLineWrap(false); + ta.insert(model.getText(), 0); + linecount = ta.getLineCount(); + + gg = new GlyphGutter(this); + + setViewportView(ta); + setRowHeaderView(gg); + + ta.getDocument().addDocumentListener(this); + } + + /* Implementation of DocumentListener interface */ + public void insertUpdate(DocumentEvent e) { + doChanged(e); + } + + public void removeUpdate(DocumentEvent e) { + doChanged(e); + } + + public void changedUpdate(DocumentEvent e) { + doChanged(e); + } + + /* If the number of lines in the JTextArea has changed then update the + GlyphGutter */ + public void doChanged(DocumentEvent e) { + isModified = true; + + if (linecount != ta.getLineCount()) { + gg.update(); + linecount = ta.getLineCount(); + } + } + + public String getText() { + return ta.getText(); + } + + public JTextArea getTextArea() { + return ta; + } + + public int getCurrentPosition() { + return model.getCurrentPosition(); + } +} + +class GlyphGutter extends JComponent { + + private PlainSourceView view; + private final String DUMMY_STRING = "99"; + + GlyphGutter(PlainSourceView view) { + this.view = view; + update(); + } + + public void update() { + JTextArea textArea = view.getTextArea(); + Font font = textArea.getFont(); + setFont(font); + + FontMetrics metrics = getFontMetrics(font); + int h = metrics.getHeight(); + int lineCount = textArea.getLineCount() + 1; + + String dummy = Integer.toString(lineCount); + if (dummy.length() < 2) { + dummy = DUMMY_STRING; + } + + Dimension d = new Dimension(); + d.width = metrics.stringWidth(dummy) + 16; + d.height = lineCount * h + 100; + setPreferredSize(d); + setSize(d); + } + + public void paintComponent(Graphics g) { + JTextArea textArea = view.getTextArea(); + + Font font = textArea.getFont(); + g.setFont(font); + + FontMetrics metrics = getFontMetrics(font); + Rectangle clip = g.getClipBounds(); + + g.setColor(getBackground()); + g.fillRect(clip.x, clip.y, clip.width, clip.height); + + int ascent = metrics.getMaxAscent(); + int h = metrics.getHeight(); + int lineCount = textArea.getLineCount() + 1; + + int startLine = clip.y / h; + int endLine = (clip.y + clip.height) / h + 1; + int width = getWidth(); + if (endLine > lineCount) { + endLine = lineCount; + } + + for (int i = startLine; i < endLine; i++) { + String text; + text = Integer.toString(i + 1) + " "; + int w = metrics.stringWidth(text); + int y = i * h; + g.setColor(Color.blue); + g.drawString(text, 0, y + ascent); + int x = width - ascent; + + // if currentPosition is not -1 then a red arrow will be drawn + if (i == view.getCurrentPosition()) { + drawArrow(g, ascent, x, y); + } + } + } + + private void drawArrow(Graphics g, int ascent, int x, int y) { + Polygon arrow = new Polygon(); + int dx = x; + y += ascent - 10; + int dy = y; + arrow.addPoint(dx, dy + 3); + arrow.addPoint(dx + 5, dy + 3); + for (x = dx + 5; x <= dx + 10; x++, y++) { + arrow.addPoint(x, y); + } + for (x = dx + 9; x >= dx + 5; x--, y++) { + arrow.addPoint(x, y); + } + arrow.addPoint(dx + 5, dy + 7); + arrow.addPoint(dx, dy + 7); + + g.setColor(Color.red); + g.fillPolygon(arrow); + g.setColor(Color.black); + g.drawPolygon(arrow); + } +}; diff --git a/scripting/java/com/sun/star/script/framework/provider/beanshell/ScriptEditorForBeanShell.java b/scripting/java/com/sun/star/script/framework/provider/beanshell/ScriptEditorForBeanShell.java new file mode 100644 index 000000000000..4fd5d85ac28d --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/provider/beanshell/ScriptEditorForBeanShell.java @@ -0,0 +1,412 @@ +/************************************************************************* +* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ +package com.sun.star.script.framework.provider.beanshell; + +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JButton; +import javax.swing.JOptionPane; + +import java.awt.FlowLayout; +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.net.URL; +import java.util.Map; +import java.util.HashMap; + +import com.sun.star.script.provider.XScriptContext; +import com.sun.star.script.framework.provider.ScriptEditor; +import com.sun.star.script.framework.container.ScriptMetaData; +import com.sun.star.script.framework.provider.ClassLoaderFactory; + +public class ScriptEditorForBeanShell + implements ScriptEditor, ActionListener +{ + private JFrame frame; + private String filename; + + private ScriptSourceModel model; + private ScriptSourceView view; + + private XScriptContext context; + private URL scriptURL = null; + private ClassLoader cl = null; + + // global ScriptEditorForBeanShell returned for getEditor() calls + private static ScriptEditorForBeanShell theScriptEditorForBeanShell; + + // global list of ScriptEditors, key is URL of file being edited + private static Map BEING_EDITED = new HashMap(); + + // template for new BeanShell scripts + private static String BSHTEMPLATE; + + // try to load the template for BeanShell scripts + static { + try { + URL url = + ScriptEditorForBeanShell.class.getResource("template.bsh"); + + InputStream in = url.openStream(); + StringBuffer buf = new StringBuffer(); + byte[] b = new byte[1024]; + int len = 0; + + while ((len = in.read(b)) != -1) { + buf.append(new String(b, 0, len)); + } + + in.close(); + + BSHTEMPLATE = buf.toString(); + } + catch (IOException ioe) { + BSHTEMPLATE = "// BeanShell script"; + } + catch (Exception e) { + BSHTEMPLATE = "// BeanShell script"; + } + } + + /** + * Returns the global ScriptEditorForBeanShell instance. + */ + public static ScriptEditorForBeanShell getEditor() + { + if (theScriptEditorForBeanShell == null) + { + synchronized(ScriptEditorForBeanShell.class) + { + if (theScriptEditorForBeanShell == null) + { + theScriptEditorForBeanShell = + new ScriptEditorForBeanShell(); + } + } + } + return theScriptEditorForBeanShell; + } + + /** + * Get the ScriptEditorForBeanShell instance for this URL + * + * @param url The URL of the script source file + * + * @return The ScriptEditorForBeanShell associated with + * the given URL if one exists, otherwise null. + */ + public static ScriptEditorForBeanShell getEditor(URL url) + { + return (ScriptEditorForBeanShell)BEING_EDITED.get(url); + } + + /** + * Returns whether or not the script source being edited in this + * ScriptEditorForBeanShell has been modified + */ + public boolean isModified() + { + return view.isModified(); + } + + /** + * Returns the text being displayed in this ScriptEditorForBeanShell + * + * @return The text displayed in this ScriptEditorForBeanShell + */ + public String getText() + { + return view.getText(); + } + + /** + * Returns the template text for BeanShell scripts + * + * @return The template text for BeanShell scripts + */ + public String getTemplate() { + return BSHTEMPLATE; + } + + /** + * Returns the default extension for BeanShell scripts + * + * @return The default extension for BeanShell scripts + */ + public String getExtension() { + return "bsh"; + } + + + /** + * Indicates the line where error occured + * + */ + public void indicateErrorLine( int lineNum ) + { + model.indicateErrorLine( lineNum ); + } + /** + * Executes the script edited by the editor + * + */ + public Object execute() throws Exception { + frame.toFront(); + return model.execute( context, cl ); + } + /** + * Opens an editor window for the specified ScriptMetaData. + * If an editor window is already open for that data it will be + * moved to the front. + * + * @param metadata The metadata describing the script + * @param context The context in which to execute the script + * + */ + public void edit(XScriptContext context, ScriptMetaData entry) { + + if (entry != null ) { + try { + ClassLoader cl = null; + try { + cl = ClassLoaderFactory.getURLClassLoader( entry ); + } + catch (Exception ignore) // TODO re-examine error handling + { + } + String sUrl = entry.getParcelLocation(); + if ( !sUrl.endsWith( "/" ) ) + { + sUrl += "/"; + } + sUrl += entry.getLanguageName(); + URL url = entry.getSourceURL(); + + // check if there is already an editing session for this script + if (BEING_EDITED.containsKey(url)) + { + ScriptEditorForBeanShell editor = + (ScriptEditorForBeanShell) BEING_EDITED.get(url); + + editor.frame.toFront(); + } + else + { + new ScriptEditorForBeanShell(context, cl, url); + } + } + catch (IOException ioe) { + showErrorMessage( "Error loading file: " + ioe.getMessage() ); + } + } + } + + private ScriptEditorForBeanShell() { + } + + private ScriptEditorForBeanShell(XScriptContext context, ClassLoader cl, + URL url) + { + this.context = context; + this.scriptURL = url; + this.model = new ScriptSourceModel(url); + this.filename = url.getFile(); + this.cl = cl; + try { + Class c = Class.forName( + "org.openoffice.netbeans.editor.NetBeansSourceView"); + + Class[] types = new Class[] { ScriptSourceModel.class }; + + java.lang.reflect.Constructor ctor = c.getConstructor(types); + + if (ctor != null) { + Object[] args = new Object[] { this.model }; + this.view = (ScriptSourceView) ctor.newInstance(args); + } + else { + this.view = new PlainSourceView(model); + } + } + catch (java.lang.Error err) { + this.view = new PlainSourceView(model); + } + catch (Exception e) { + this.view = new PlainSourceView(model); + } + + this.model.setView(this.view); + initUI(); + frame.show(); + + BEING_EDITED.put(url, this); + } + + private void showErrorMessage(String message) { + JOptionPane.showMessageDialog(frame, message, + "Error", JOptionPane.ERROR_MESSAGE); + } + + private void initUI() { + frame = new JFrame("BeanShell Debug Window: " + filename); + frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + + frame.addWindowListener( + new WindowAdapter() + { + public void windowClosing(WindowEvent e) { + doClose(); + } + } + ); + + String[] labels = {"Run", "Clear", "Save", "Close"}; + JPanel p = new JPanel(); + p.setLayout(new FlowLayout()); + + for (int i = 0; i < labels.length; i++) { + JButton b = new JButton(labels[i]); + b.addActionListener(this); + p.add(b); + + if (labels[i].equals("Save") && filename == null) { + b.setEnabled(false); + } + } + + frame.getContentPane().add((JComponent)view, "Center"); + frame.getContentPane().add(p, "South"); + frame.pack(); + frame.setSize(590, 480); + frame.setLocation(300, 200); + } + + private void doClose() { + if (view.isModified()) { + int result = JOptionPane.showConfirmDialog(frame, + "The script has been modified. " + + "Do you want to save the changes?"); + + if (result == JOptionPane.CANCEL_OPTION) + { + // don't close the window, just return + return; + } + else if (result == JOptionPane.YES_OPTION) + { + boolean saveSuccess = saveTextArea(); + if (saveSuccess == false) + { + return; + } + } + } + frame.dispose(); + shutdown(); + } + + private boolean saveTextArea() { + boolean result = true; + + if (!view.isModified()) { + return true; + } + + OutputStream fos = null; + try { + String s = view.getText(); + fos = scriptURL.openConnection().getOutputStream(); + if ( fos != null) { + fos.write(s.getBytes()); + } + else + { + showErrorMessage( + "Error saving script: Could not open stream for file" ); + result = false; + } + view.setModified(false); + } + catch (IOException ioe) { + showErrorMessage( "Error saving script: " + ioe.getMessage() ); + result = false; + } + catch (Exception e) { + showErrorMessage( "Error saving script: " + e.getMessage() ); + result = false; + } + finally { + if (fos != null) { + try { + fos.flush(); + if ( fos != null ) + { + fos.close(); + } + } + catch (IOException ignore) { + } + } + } + return result; + } + + private void shutdown() + { + if (BEING_EDITED.containsKey(scriptURL)) { + BEING_EDITED.remove(scriptURL); + } + } + + public void actionPerformed(ActionEvent e) { + if (e.getActionCommand().equals("Run")) { + try + { + execute(); + } + catch (Exception invokeException ) { + showErrorMessage(invokeException.getMessage()); + } + } + else if (e.getActionCommand().equals("Close")) { + doClose(); + } + else if (e.getActionCommand().equals("Save")) { + saveTextArea(); + } + else if (e.getActionCommand().equals("Clear")) { + view.clear(); + } + } +} diff --git a/scripting/java/com/sun/star/script/framework/provider/beanshell/ScriptProviderForBeanShell.java b/scripting/java/com/sun/star/script/framework/provider/beanshell/ScriptProviderForBeanShell.java new file mode 100755 index 000000000000..95c727881427 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/provider/beanshell/ScriptProviderForBeanShell.java @@ -0,0 +1,383 @@ +/************************************************************************* +* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ +package com.sun.star.script.framework.provider.beanshell; + +import com.sun.star.uno.XComponentContext; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.XSingleServiceFactory; +import com.sun.star.registry.XRegistryKey; +import com.sun.star.comp.loader.FactoryHelper; +import com.sun.star.frame.XModel; +import com.sun.star.uno.Type; +import com.sun.star.uno.Any; + +import com.sun.star.reflection.InvocationTargetException; + +import java.util.StringTokenizer; + +import java.net.URL; + +import bsh.Interpreter; + +import com.sun.star.document.XScriptInvocationContext; +import com.sun.star.script.provider.XScript; +import com.sun.star.script.provider.ScriptErrorRaisedException; +import com.sun.star.script.provider.ScriptExceptionRaisedException; +import com.sun.star.script.provider.ScriptFrameworkErrorException; +import com.sun.star.script.provider.ScriptFrameworkErrorType; + + +import com.sun.star.script.framework.provider.*; +import com.sun.star.script.framework.log.*; +import com.sun.star.script.framework.container.ScriptMetaData; + +public class ScriptProviderForBeanShell +{ + public static class _ScriptProviderForBeanShell extends ScriptProvider + { + public _ScriptProviderForBeanShell(XComponentContext ctx) + { + super (ctx, "BeanShell"); + } + + public XScript getScript( /*IN*/String scriptURI ) + throws com.sun.star.uno.RuntimeException, + ScriptFrameworkErrorException + { + ScriptMetaData scriptData = null; + try + { + scriptData = getScriptData( scriptURI ); + ScriptImpl script = new ScriptImpl( m_xContext, scriptData, m_xModel, m_xInvocContext ); + return script; + } + catch ( com.sun.star.uno.RuntimeException re ) + { + throw new ScriptFrameworkErrorException( "Failed to create script object: " + re.getMessage(), + null, scriptData.getLanguageName(), language, ScriptFrameworkErrorType.UNKNOWN ); + } + } + + public boolean hasScriptEditor() + { + return true; + } + + public ScriptEditor getScriptEditor() + { + return ScriptEditorForBeanShell.getEditor(); + } + } + + /** + * Returns a factory for creating the service. + * This method is called by the <code>JavaLoader</code> + * <p> + * + * @param implName the name of the implementation for which a service is desired + * @param multiFactory the service manager to be used if needed + * @param regKey the registryKey + * @return returns a <code>XSingleServiceFactory</code> for creating + * the component + * @see com.sun.star.comp.loader.JavaLoader + */ + public static XSingleServiceFactory __getServiceFactory( String implName, + XMultiServiceFactory multiFactory, + XRegistryKey regKey ) + { + XSingleServiceFactory xSingleServiceFactory = null; + + if ( implName.equals( ScriptProviderForBeanShell._ScriptProviderForBeanShell.class.getName() ) ) + { + xSingleServiceFactory = FactoryHelper.getServiceFactory( + ScriptProviderForBeanShell._ScriptProviderForBeanShell.class, + "com.sun.star.script.ScriptProviderForBeanShell", + multiFactory, + regKey ); + } + + return xSingleServiceFactory; + } +} + +class ScriptImpl implements XScript +{ + private ScriptMetaData metaData; + private XComponentContext m_xContext; + private XMultiComponentFactory m_xMultiComponentFactory; + private XModel m_xModel; + private XScriptInvocationContext m_xInvocContext; + + ScriptImpl( XComponentContext ctx, ScriptMetaData metaData, XModel xModel, + XScriptInvocationContext xContext ) throws com.sun.star.uno.RuntimeException + { + this.metaData = metaData; + this.m_xContext = ctx; + this.m_xModel = xModel; + this.m_xInvocContext = xContext; + + try + { + this.m_xMultiComponentFactory = m_xContext.getServiceManager(); + } + catch ( Exception e ) + { + LogUtils.DEBUG( LogUtils.getTrace( e ) ); + throw new com.sun.star.uno.RuntimeException( + "Error constructing ScriptImpl [beanshell]: " + + e.getMessage() ); + } + + LogUtils.DEBUG("ScriptImpl [beanshell] script data = " + metaData ); + } + /** + * documentStorageID and document reference + * for use in script name resolving + * + * @param aParams All parameters; pure, out params are + * undefined in sequence, i.e., the value + * has to be ignored by the callee + * + * @param aOutParamIndex Out indices + * + * @param aOutParam Out parameters + * + * @returns The value returned from the function + * being invoked + * + * @throws IllegalArgumentException If there is no matching script name + * + * @throws CannotConvertException If args do not match or cannot + * be converted the those of the + * invokee + * + * @throws InvocationTargetException If the running script throws + * an exception this information + * is captured and rethrown as + * this exception type. + */ + + public Object invoke( /*IN*/Object[] aParams, + /*OUT*/short[][] aOutParamIndex, + /*OUT*/Object[][] aOutParam ) + throws ScriptFrameworkErrorException, + InvocationTargetException + { + // Initialise the out paramters - not used at the moment + aOutParamIndex[0] = new short[0]; + aOutParam[0] = new Object[0]; + + + ClassLoader cl = null; + URL sourceUrl = null; + try { + cl = ClassLoaderFactory.getURLClassLoader( metaData ); + sourceUrl = metaData.getSourceURL(); + } + catch ( java.net.MalformedURLException mfu ) + { + // Framework error + throw new ScriptFrameworkErrorException( + mfu.getMessage(), null, + metaData.getLanguageName(), metaData.getLanguage(), + ScriptFrameworkErrorType.MALFORMED_URL ); + } + catch ( NoSuitableClassLoaderException nsc ) + { + // Framework error + throw new ScriptFrameworkErrorException( + nsc.getMessage(), null, + metaData.getLanguageName(), metaData.getLanguage(), + ScriptFrameworkErrorType.UNKNOWN ); + } + // Set class loader to be used for class files + // and jar files + Thread.currentThread().setContextClassLoader(cl); + Interpreter interpreter = new Interpreter(); + + interpreter.getNameSpace().clear(); + // Set class loader to be used by interpreter + // to look for classes by source e.g. interpreter + // will use this classloader to search classpath + // for source file ( bla.java ) on import or reference + interpreter.setClassLoader(cl); + try { + interpreter.set("XSCRIPTCONTEXT", + ScriptContext.createContext(m_xModel, m_xInvocContext, + m_xContext, m_xMultiComponentFactory)); + + interpreter.set("ARGUMENTS", aParams); + } + catch (bsh.EvalError e) { + // Framework error setting up context + throw new ScriptFrameworkErrorException( + e.getMessage(), null, + metaData.getLanguageName(), metaData.getLanguage(), + ScriptFrameworkErrorType.UNKNOWN ); + } + + try { + String source = null; + Object result = null; + + ScriptEditorForBeanShell editor = + ScriptEditorForBeanShell.getEditor( + sourceUrl ); + + if ( editor != null ) + { + result = editor.execute(); + + if (result == null) + { + return new Any(new Type(), null); + } + return result; + } + + metaData.loadSource(); + source = metaData.getSource(); + + if ( source == null || source.length() == 0 ) + { + throw new ScriptFrameworkErrorException( + "Failed to read script", null, + metaData.getLanguageName(), metaData.getLanguage(), + ScriptFrameworkErrorType.NO_SUCH_SCRIPT ); + } + result = interpreter.eval( source ); + + if (result == null) + { + return new Any(new Type(), null); + } + return result; + } + catch ( bsh.ParseException pe ) + { + throw new InvocationTargetException( "Beanshell failed to parse " + metaData.getLanguageName(), null, processBshException( pe, metaData.getLanguageName() ) ); + } + catch ( bsh.TargetError te ) + { + throw new InvocationTargetException( "Beanshell uncaught exception for " + metaData.getLanguageName(), null, processBshException( te, metaData.getLanguageName() ) ); + } + catch ( bsh.EvalError ex ) + { + throw new InvocationTargetException( "Beanshell error for " + metaData.getLanguageName(), null, processBshException( ex, metaData.getLanguageName() ) ); + } + catch ( Exception e ) + { + throw new ScriptFrameworkErrorException( + "Failed to read script", null, + metaData.getLanguageName(), metaData.getLanguage(), + ScriptFrameworkErrorType.UNKNOWN ); + } + } + private void raiseEditor( int lineNum ) + { + ScriptEditorForBeanShell editor = null; + try + { + URL sourceUrl = metaData.getSourceURL(); + editor = ScriptEditorForBeanShell.getEditor( sourceUrl ); + if ( editor == null ) + { + editor = ScriptEditorForBeanShell.getEditor(); + editor.edit( + ScriptContext.createContext(m_xModel, m_xInvocContext, + m_xContext, m_xMultiComponentFactory), metaData ); + editor = ScriptEditorForBeanShell.getEditor( sourceUrl ); + } + if ( editor != null ) + { + editor.indicateErrorLine( lineNum ); + } + } + catch( Exception ignore ) + { + } + } + + private ScriptErrorRaisedException processBshException( bsh.EvalError e, String script ) + { + LogUtils.DEBUG("Beanshell error RAW message " + e.getMessage()); + String message = e.getMessage(); + int usefullInfoIndex = message.lastIndexOf("\' :" ); + int lineNum = e.getErrorLineNumber(); + + raiseEditor( lineNum ); + + //String stackTrace = te.getScriptStackTrace(); // never seems to have any info?? + if ( usefullInfoIndex > -1 ) + { + message = message.substring( usefullInfoIndex + 2 ); + } + if ( e instanceof bsh.TargetError ) + { + LogUtils.DEBUG("got instance of TargetError"); + if ( usefullInfoIndex == -1 ) + { + message = ( ( bsh.TargetError)e ).getTarget().getMessage(); + } + String wrappedException = ""; + String full = e.toString(); + int index = full.indexOf( "Target exception:" ); + if ( index > -1 ) + { + String toParse = full.substring( index ); + LogUtils.DEBUG("About to parse " + toParse ); + StringTokenizer tokenizer = new StringTokenizer( full.substring( index ),":" ); + if ( tokenizer.countTokens() > 2 ) + { + LogUtils.DEBUG("First token = " + (String)tokenizer.nextElement()); + wrappedException = (String)tokenizer.nextElement(); + LogUtils.DEBUG("wrapped exception = = " + wrappedException ); + } + } + ScriptExceptionRaisedException se = new ScriptExceptionRaisedException( message); + se.lineNum = lineNum; + se.scriptName = script; + se.exceptionType = wrappedException; + se.language = "BeanShell"; + LogUtils.DEBUG("UnCaught Exception error: " ); + LogUtils.DEBUG("\tscript: " + script ); + LogUtils.DEBUG("\tline: " + lineNum ); + LogUtils.DEBUG("\twrapped exception: " + wrappedException ); + LogUtils.DEBUG("\tmessage: " + message ); + return se; + } + else + { + LogUtils.DEBUG("Error or ParseError Exception error: " ); + LogUtils.DEBUG("\tscript: " + script ); + LogUtils.DEBUG("\tline: " + lineNum ); + LogUtils.DEBUG("\tmessage: " + message ); + return new ScriptErrorRaisedException( message, null, script, "BeanShell", lineNum ); + } + } +} diff --git a/scripting/java/com/sun/star/script/framework/provider/beanshell/ScriptSourceModel.java b/scripting/java/com/sun/star/script/framework/provider/beanshell/ScriptSourceModel.java new file mode 100644 index 000000000000..05b2850f33a8 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/provider/beanshell/ScriptSourceModel.java @@ -0,0 +1,141 @@ +/************************************************************************* +* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ +package com.sun.star.script.framework.provider.beanshell; + +import java.io.InputStream; +import java.io.IOException; + +import java.net.URL; + +import com.sun.star.script.provider.XScriptContext; + +public class ScriptSourceModel { + + private int currentPosition = -1; + private URL file = null; + private ScriptSourceView view = null; + + public ScriptSourceModel(URL file ) { + this.file = file; + } + + private String load() throws IOException { + StringBuffer buf = new StringBuffer(); + InputStream in = file.openStream(); + + byte[] contents = new byte[1024]; + int len = 0; + + while ((len = in.read(contents, 0, 1024)) != -1) { + buf.append(new String(contents, 0, len)); + } + + try { + in.close(); + } + catch (IOException ignore) { + } + + return buf.toString(); + } + + public String getText() { + String result = ""; + + try { + result = load(); + } + catch (IOException ioe) { + // do nothing, empty string will be returned + } + + return result; + } + + public int getCurrentPosition() { + return this.currentPosition; + } + + public void setView(ScriptSourceView view) { + this.view = view; + } + + public Object execute(final XScriptContext context, ClassLoader cl ) + throws Exception + { + Object result = null; + // Thread execThread = new Thread() { + // public void run() { + if ( cl != null ) + { + // sets this threads class loader + // hopefully any threads spawned by this + // will inherit this cl + // this enables any class files imported + // from the interpreter to be loaded + // note: setting the classloader on the + // interpreter has a slightly different + // meaning in that the classloader for + // the interpreter seems only to look for + // source files ( bla.java ) in the classpath + Thread.currentThread().setContextClassLoader(cl); + } + bsh.Interpreter interpreter = new bsh.Interpreter(); + if ( cl != null ) + { + // additionally set class loader on the interpreter + // to allow it to load java classes defined in source + // files e.g. bla.java + interpreter.getNameSpace().clear(); + } + + + // reset position + currentPosition = -1; + view.update(); + + interpreter.set("XSCRIPTCONTEXT", context); + interpreter.set("ARGUMENTS", new Object[0]); + + if (view.isModified()) { + result = interpreter.eval(view.getText()); + } + else { + result = interpreter.eval(getText()); + } + // } + // }; + // execThread.start(); + return result; + } + public void indicateErrorLine( int lineNum ) + { + System.out.println("Beanshell indicateErrorLine " + lineNum ); + currentPosition = lineNum - 1; + view.update(); + } +} diff --git a/scripting/java/com/sun/star/script/framework/provider/beanshell/ScriptSourceView.java b/scripting/java/com/sun/star/script/framework/provider/beanshell/ScriptSourceView.java new file mode 100644 index 000000000000..22b4e375aa05 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/provider/beanshell/ScriptSourceView.java @@ -0,0 +1,35 @@ +/************************************************************************* +* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * +************************************************************************/ +package com.sun.star.script.framework.provider.beanshell; + +public interface ScriptSourceView { + public void clear(); + public void update(); + public boolean isModified(); + public void setModified(boolean value); + public String getText(); +} diff --git a/scripting/java/com/sun/star/script/framework/provider/beanshell/template.bsh b/scripting/java/com/sun/star/script/framework/provider/beanshell/template.bsh new file mode 100644 index 000000000000..03cb114d79b7 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/provider/beanshell/template.bsh @@ -0,0 +1,48 @@ +/* + Import standard OpenOffice.org API classes. For more information on + these classes and the OpenOffice.org API, see the OpenOffice.org + Developers Guide at: + + http://api.openoffice.org/ +*/ + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; +import com.sun.star.frame.XDesktop; +import com.sun.star.frame.XModel; + +/* + Import XScriptContext class. An instance of this class is available + to all BeanShell scripts in the global variable "XSCRIPTCONTEXT". This + variable can be used to access the document for which this script + was invoked. + + Methods available are: + + XSCRIPTCONTEXT.getDocument() returns XModel + XSCRIPTCONTEXT.getInvocationContext() returns XScriptInvocationContext or NULL + XSCRIPTCONTEXT.getDesktop() returns XDesktop + XSCRIPTCONTEXT.getComponentContext() returns XComponentContext + + For more information on using this class see the scripting + developer guides at: + + http://api.openoffice.org/docs/DevelopersGuide/ScriptingFramework/ScriptingFramework.xhtml +*/ + +// Hello World in BeanShell +import com.sun.star.text.XTextDocument; +import com.sun.star.text.XText; +import com.sun.star.text.XTextRange; + +oDoc = UnoRuntime.queryInterface(XModel.class,XSCRIPTCONTEXT.getInvocationContext()); +if ( oDoc == null ) + oDoc = XSCRIPTCONTEXT.getDocument(); + +xTextDoc = (XTextDocument) UnoRuntime.queryInterface(XTextDocument.class,oDoc); +xText = xTextDoc.getText(); +xTextRange = xText.getEnd(); +xTextRange.setString( "Hello World (in BeanShell)" ); + +// BeanShell OpenOffice.org scripts should always return 0 +return 0; |