diff options
Diffstat (limited to 'scripting/java/com/sun/star/script')
42 files changed, 9551 insertions, 0 deletions
diff --git a/scripting/java/com/sun/star/script/framework/browse/DialogFactory.java b/scripting/java/com/sun/star/script/framework/browse/DialogFactory.java new file mode 100644 index 000000000000..de7986e9ab02 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/browse/DialogFactory.java @@ -0,0 +1,423 @@ +/************************************************************************* + * + * 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.browse; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.XComponentContext; + +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.lang.XMultiServiceFactory; +import com.sun.star.lang.EventObject; + +import com.sun.star.beans.XPropertySet; +import com.sun.star.container.XNameContainer; + +import com.sun.star.awt.*; + + +public class DialogFactory +{ + private static DialogFactory factory; + private XComponentContext xComponentContext; + + // singleton + private DialogFactory(XComponentContext xComponentContext) + { + this.xComponentContext = xComponentContext; + factory = this; + } + + public static void createDialogFactory(XComponentContext xComponentContext) + { + if (factory == null) + { + synchronized(DialogFactory.class) + { + if (factory == null) + { + factory = new DialogFactory(xComponentContext); + } + } + } + } + + public static DialogFactory getDialogFactory() + throws java.lang.Exception + { + if (factory == null) + { + throw new java.lang.Exception("DialogFactory not initialized"); + } + return factory; + } + + public boolean showConfirmDialog(String title, String prompt) + { + final XDialog xDialog; + try + { + xDialog = createConfirmDialog(title, prompt); + } + catch (com.sun.star.uno.Exception e) + { + return false; + } + + // add an action listener to the button controls + XControlContainer controls = (XControlContainer) + UnoRuntime.queryInterface(XControlContainer.class, xDialog); + + XButton okButton = (XButton) UnoRuntime.queryInterface( + XButton.class, controls.getControl("Ok")); + okButton.setActionCommand("Ok"); + + XButton cancelButton = (XButton) UnoRuntime.queryInterface( + XButton.class, controls.getControl("Cancel")); + cancelButton.setActionCommand("Cancel"); + + final ResultHolder resultHolder = new ResultHolder(); + + com.sun.star.awt.XActionListener listener = + new com.sun.star.awt.XActionListener() + { + public void actionPerformed(com.sun.star.awt.ActionEvent e) { + if (e.ActionCommand.equals("Cancel")) + { + resultHolder.setResult(Boolean.FALSE); + xDialog.endExecute(); + } + else + { + resultHolder.setResult(Boolean.TRUE); + xDialog.endExecute(); + } + } + + public void disposing(EventObject o) { + // does nothing + } + }; + + okButton.addActionListener(listener); + cancelButton.addActionListener(listener); + + xDialog.execute(); + + Boolean result = (Boolean)resultHolder.getResult(); + + return result == null ? false : result.booleanValue(); + } + + public String showInputDialog(String title, String prompt) + { + final XDialog xDialog; + try + { + xDialog = createInputDialog(title, prompt); + } + catch (com.sun.star.uno.Exception e) + { + return null; + } + + // add an action listener to the button controls + XControlContainer controls = (XControlContainer) + UnoRuntime.queryInterface(XControlContainer.class, xDialog); + + XButton okButton = (XButton) UnoRuntime.queryInterface( + XButton.class, controls.getControl("Ok")); + okButton.setActionCommand("Ok"); + + XButton cancelButton = (XButton) UnoRuntime.queryInterface( + XButton.class, controls.getControl("Cancel")); + cancelButton.setActionCommand("Cancel"); + + final XTextComponent textField = (XTextComponent) + UnoRuntime.queryInterface( + XTextComponent.class, controls.getControl("NameField")); + + final ResultHolder resultHolder = new ResultHolder(); + + com.sun.star.awt.XActionListener listener = + new com.sun.star.awt.XActionListener() + { + public void actionPerformed(com.sun.star.awt.ActionEvent e) { + if (e.ActionCommand.equals("Cancel")) + { + resultHolder.setResult(null); + xDialog.endExecute(); + } + else + { + resultHolder.setResult(textField.getText()); + xDialog.endExecute(); + } + } + + public void disposing(EventObject o) { + // does nothing + } + }; + + okButton.addActionListener(listener); + cancelButton.addActionListener(listener); + + xDialog.execute(); + + return (String)resultHolder.getResult(); + } + + private XDialog createConfirmDialog(String title, String prompt) + throws com.sun.star.uno.Exception + { + if (title == null || title.equals("")) + { + title = "Scripting Framework"; + } + + if (prompt == null || prompt.equals("")) + { + prompt = "Enter name"; + } + + // get the service manager from the component context + XMultiComponentFactory xMultiComponentFactory = + xComponentContext.getServiceManager(); + + // create the dialog model and set the properties + Object dialogModel = xMultiComponentFactory.createInstanceWithContext( + "com.sun.star.awt.UnoControlDialogModel", xComponentContext); + + XPropertySet props = (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, dialogModel); + + props.setPropertyValue("Title", title); + setDimensions(dialogModel, 100, 100, 157, 37); + + // get the service manager from the dialog model + XMultiServiceFactory xMultiServiceFactory = + (XMultiServiceFactory) UnoRuntime.queryInterface( + XMultiServiceFactory.class, dialogModel); + + // create the label model and set the properties + Object label = xMultiServiceFactory.createInstance( + "com.sun.star.awt.UnoControlFixedTextModel"); + + setDimensions(label, 15, 5, 134, 12); + + XPropertySet labelProps = (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, label); + labelProps.setPropertyValue("Name", "PromptLabel"); + labelProps.setPropertyValue("Label", prompt); + + // create the Run Macro button model and set the properties + Object okButtonModel = xMultiServiceFactory.createInstance( + "com.sun.star.awt.UnoControlButtonModel"); + + setDimensions(okButtonModel, 40, 18, 38, 15); + + XPropertySet buttonProps = (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, okButtonModel); + buttonProps.setPropertyValue("Name", "Ok"); + buttonProps.setPropertyValue("Label", "Ok"); + + // create the Dont Run Macro button model and set the properties + Object cancelButtonModel = xMultiServiceFactory.createInstance( + "com.sun.star.awt.UnoControlButtonModel"); + + setDimensions(cancelButtonModel, 83, 18, 38, 15); + + buttonProps = (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, cancelButtonModel); + buttonProps.setPropertyValue("Name", "Cancel"); + buttonProps.setPropertyValue("Label", "Cancel"); + + // insert the control models into the dialog model + XNameContainer xNameCont = (XNameContainer) UnoRuntime.queryInterface( + XNameContainer.class, dialogModel); + + xNameCont.insertByName("PromptLabel", label); + xNameCont.insertByName("Ok", okButtonModel); + xNameCont.insertByName("Cancel", cancelButtonModel); + + // create the dialog control and set the model + Object dialog = xMultiComponentFactory.createInstanceWithContext( + "com.sun.star.awt.UnoControlDialog", xComponentContext); + XControl xControl = (XControl) UnoRuntime.queryInterface( + XControl.class, dialog); + + XControlModel xControlModel = (XControlModel) + UnoRuntime.queryInterface(XControlModel.class, dialogModel); + xControl.setModel(xControlModel); + + // create a peer + Object toolkit = xMultiComponentFactory.createInstanceWithContext( + "com.sun.star.awt.ExtToolkit", xComponentContext); + XToolkit xToolkit = (XToolkit) UnoRuntime.queryInterface( + XToolkit.class, toolkit); + XWindow xWindow = (XWindow) UnoRuntime.queryInterface( + XWindow.class, xControl); + xWindow.setVisible(false); + xControl.createPeer(xToolkit, null); + + return (XDialog) UnoRuntime.queryInterface(XDialog.class, dialog); + } + + private void setDimensions(Object o, int x, int y, int width, int height) + throws com.sun.star.uno.Exception + { + XPropertySet props = (XPropertySet) + UnoRuntime.queryInterface(XPropertySet.class, o); + + props.setPropertyValue("PositionX", new Integer(x)); + props.setPropertyValue("PositionY", new Integer(y)); + props.setPropertyValue("Height", new Integer(height)); + props.setPropertyValue("Width", new Integer(width)); + } + + private XDialog createInputDialog(String title, String prompt) + throws com.sun.star.uno.Exception + { + if (title == null || title.equals("")) + { + title = "Scripting Framework"; + } + + if (prompt == null || prompt.equals("")) + { + prompt = "Enter name"; + } + + // get the service manager from the component context + XMultiComponentFactory xMultiComponentFactory = + xComponentContext.getServiceManager(); + + // create the dialog model and set the properties + Object dialogModel = xMultiComponentFactory.createInstanceWithContext( + "com.sun.star.awt.UnoControlDialogModel", xComponentContext); + + setDimensions(dialogModel, 100, 100, 157, 58); + + XPropertySet props = (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, dialogModel); + props.setPropertyValue("Title", title); + + // get the service manager from the dialog model + XMultiServiceFactory xMultiServiceFactory = + (XMultiServiceFactory) UnoRuntime.queryInterface( + XMultiServiceFactory.class, dialogModel); + + // create the label model and set the properties + Object label = xMultiServiceFactory.createInstance( + "com.sun.star.awt.UnoControlFixedTextModel"); + + setDimensions(label, 15, 5, 134, 12); + + XPropertySet labelProps = (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, label); + labelProps.setPropertyValue("Name", "PromptLabel"); + labelProps.setPropertyValue("Label", prompt); + + // create the text field + Object edit = xMultiServiceFactory.createInstance( + "com.sun.star.awt.UnoControlEditModel"); + + setDimensions(edit, 15, 18, 134, 12); + + XPropertySet editProps = (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, edit); + editProps.setPropertyValue("Name", "NameField"); + + // create the OK button + Object okButtonModel = xMultiServiceFactory.createInstance( + "com.sun.star.awt.UnoControlButtonModel"); + + setDimensions(okButtonModel, 40, 39, 38, 15); + + XPropertySet buttonProps = (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, okButtonModel); + buttonProps.setPropertyValue("Name", "Ok"); + buttonProps.setPropertyValue("Label", "Ok"); + + // create the Cancel button + Object cancelButtonModel = xMultiServiceFactory.createInstance( + "com.sun.star.awt.UnoControlButtonModel"); + + setDimensions(cancelButtonModel, 83, 39, 38, 15); + + buttonProps = (XPropertySet) UnoRuntime.queryInterface( + XPropertySet.class, cancelButtonModel); + buttonProps.setPropertyValue("Name", "Cancel"); + buttonProps.setPropertyValue("Label", "Cancel"); + + // insert the control models into the dialog model + XNameContainer xNameCont = (XNameContainer) + UnoRuntime.queryInterface(XNameContainer.class, dialogModel); + + xNameCont.insertByName("PromptLabel", label); + xNameCont.insertByName("NameField", edit); + xNameCont.insertByName("Ok", okButtonModel); + xNameCont.insertByName("Cancel", cancelButtonModel); + + // create the dialog control and set the model + Object dialog = xMultiComponentFactory.createInstanceWithContext( + "com.sun.star.awt.UnoControlDialog", xComponentContext); + XControl xControl = (XControl) UnoRuntime.queryInterface( + XControl.class, dialog); + + XControlModel xControlModel = (XControlModel) + UnoRuntime.queryInterface(XControlModel.class, dialogModel); + xControl.setModel(xControlModel); + + // create a peer + Object toolkit = xMultiComponentFactory.createInstanceWithContext( + "com.sun.star.awt.ExtToolkit", xComponentContext); + XToolkit xToolkit = (XToolkit) UnoRuntime.queryInterface( + XToolkit.class, toolkit); + XWindow xWindow = (XWindow) UnoRuntime.queryInterface( + XWindow.class, xControl); + xWindow.setVisible(false); + xControl.createPeer(xToolkit, null); + + return (XDialog) UnoRuntime.queryInterface(XDialog.class, dialog); + } + + private static class ResultHolder { + private Object result = null; + + public Object getResult() + { + return result; + } + + public void setResult(Object result) + { + this.result = result; + } + } +} diff --git a/scripting/java/com/sun/star/script/framework/browse/ParcelBrowseNode.java b/scripting/java/com/sun/star/script/framework/browse/ParcelBrowseNode.java new file mode 100644 index 000000000000..974b001d5d35 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/browse/ParcelBrowseNode.java @@ -0,0 +1,376 @@ +/************************************************************************* + * + * 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.browse; + +import com.sun.star.beans.XIntrospectionAccess; + +import com.sun.star.lib.uno.helper.PropertySet; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.Any; +import com.sun.star.uno.AnyConverter; +import com.sun.star.uno.Type; +import com.sun.star.uno.XComponentContext; + + +import com.sun.star.lang.XMultiComponentFactory; + + +import com.sun.star.script.XInvocation; + +import com.sun.star.ucb.XSimpleFileAccess; + +import com.sun.star.script.browse.XBrowseNode; +import com.sun.star.script.browse.BrowseNodeTypes; + +import com.sun.star.script.framework.provider.ScriptProvider; +import com.sun.star.script.framework.log.LogUtils; +import com.sun.star.script.framework.container.ScriptMetaData; +import com.sun.star.script.framework.container.ScriptEntry; +import com.sun.star.script.framework.container.Parcel; +import com.sun.star.script.framework.container.ParcelContainer; +import com.sun.star.script.framework.browse.DialogFactory; + +import java.util.*; +import javax.swing.JOptionPane; + +public class ParcelBrowseNode extends PropertySet + implements XBrowseNode, XInvocation +{ + private ScriptProvider provider; + //private RootBrowseNode parent; + private Collection browsenodes; + private String name; + private ParcelContainer container; + private Parcel parcel; + public boolean deletable = true; + public boolean editable = false; + public boolean creatable = false; + public boolean renamable = true; + + public ParcelBrowseNode( ScriptProvider provider, ParcelContainer container, String parcelName ) { + this.provider = provider; + this.name = parcelName; + this.container = container; + + // TODO decide whether exception is propagated out or not + try + { + this.parcel = (Parcel)this.container.getByName( parcelName ); + } + catch ( Exception e ) + { + + LogUtils.DEBUG("** Exception: " + e ); + LogUtils.DEBUG(" ** Failed to get parcel named " + + parcelName + " from container" ); + } + registerProperty("Deletable", new Type(boolean.class), + (short)0, "deletable"); + registerProperty("Editable", new Type(boolean.class), + (short)0, "editable"); + registerProperty("Creatable", new Type(boolean.class), + (short)0, "creatable"); + registerProperty("Renamable", new Type(boolean.class), + (short)0, "renamable"); + if (provider.hasScriptEditor() == true) + { + this.creatable = true; + } + + String parcelDirUrl = parcel.getPathToParcel(); + XComponentContext xCtx = provider.getScriptingContext().getComponentContext(); + XMultiComponentFactory xFac = xCtx.getServiceManager(); + try + { + XSimpleFileAccess xSFA = ( XSimpleFileAccess) + UnoRuntime.queryInterface( XSimpleFileAccess.class, + xFac.createInstanceWithContext( + "com.sun.star.ucb.SimpleFileAccess", + xCtx ) ); + if ( xSFA != null && ( xSFA.isReadOnly( parcelDirUrl ) || + container.isUnoPkg() ) ) + { + deletable = false; + editable = false; + creatable = false; + renamable = false; + } + } + catch ( com.sun.star.uno.Exception e ) + { + // TODO propagate potential errors + // Pthrow new com.sun.star.uno.RuntimeException( e.toString() ); + LogUtils.DEBUG( "Caught exception creating ParcelBrowseNode " + e ); + LogUtils.DEBUG( LogUtils.getTrace( e ) ); + } + + } + + public String getName() { + return parcel.getName(); + } + + public XBrowseNode[] getChildNodes() { + try + { + + if ( hasChildNodes() ) + { + String[] names = parcel.getElementNames(); + browsenodes = new ArrayList( names.length ); + + for ( int index = 0; index < names.length; index++ ) + { + browsenodes.add( new ScriptBrowseNode( provider, parcel, names[ index ] )); + } + } + else + { + LogUtils.DEBUG("ParcelBrowseNode.getChildeNodes no children " ); + return new XBrowseNode[0]; + } + } + catch ( Exception e ) + { + LogUtils.DEBUG("Failed to getChildeNodes, exception: " + e ); + LogUtils.DEBUG( LogUtils.getTrace( e ) ); + return new XBrowseNode[0]; + } + return (XBrowseNode[])browsenodes.toArray(new XBrowseNode[0]); + } + + public boolean hasChildNodes() { + if ( container != null && container.hasByName( getName() ) && parcel != null ) + { + return parcel.hasElements(); + } + + return false; + } + + public short getType() { + return BrowseNodeTypes.CONTAINER; + } + + public String toString() + { + return getName(); + } + + // implementation of XInvocation interface + public XIntrospectionAccess getIntrospection() { + return null; + } + + public Object invoke(String aFunctionName, Object[] aParams, + short[][] aOutParamIndex, Object[][] aOutParam) + throws com.sun.star.lang.IllegalArgumentException, + com.sun.star.script.CannotConvertException, + com.sun.star.reflection.InvocationTargetException + { + LogUtils.DEBUG("ParcelBrowseNode invoke for " + aFunctionName ); + // Initialise the out paramters - not used but prevents error in + // UNO bridge + aOutParamIndex[0] = new short[0]; + aOutParam[0] = new Object[0]; + + Any result = new Any(new Type(Boolean.class), Boolean.TRUE); + + if (aFunctionName.equals("Creatable")) + { + try + { + String newName; + + if (aParams == null || aParams.length < 1 || + AnyConverter.isString(aParams[0]) == false) + { + String prompt = "Enter name for new Script"; + String title = "Create Script"; + + // try to get a DialogFactory instance, if it fails + // just use a Swing JOptionPane to prompt for the name + try + { + DialogFactory dialogFactory = + DialogFactory.getDialogFactory(); + + newName = dialogFactory.showInputDialog(title, prompt); + } + catch (Exception e) + { + newName = JOptionPane.showInputDialog(null, prompt, title, + JOptionPane.QUESTION_MESSAGE); + } + } + else { + newName = (String) AnyConverter.toString(aParams[0]); + } + + if ( newName == null || newName.equals("")) + { + result = new Any(new Type(Boolean.class), Boolean.FALSE); + } + else + { + String source = new String(provider.getScriptEditor().getTemplate().getBytes()); + String languageName = newName + "." + provider.getScriptEditor().getExtension(); + String language = container.getLanguage(); + + ScriptEntry entry = new ScriptEntry( language, languageName, languageName, "", new HashMap() ); + + Parcel parcel = (Parcel)container.getByName( getName() ); + ScriptMetaData data = new ScriptMetaData( parcel, entry, source ); + parcel.insertByName( languageName, data ); + + ScriptBrowseNode sbn = new ScriptBrowseNode( provider, parcel, languageName ); + + if(browsenodes==null) + { + LogUtils.DEBUG("browsenodes null!!"); + browsenodes = new ArrayList(4); + } + browsenodes.add(sbn); + + result = new Any(new Type(XBrowseNode.class), sbn); + } + } + catch (Exception e) + { + LogUtils.DEBUG("ParcelBrowseNode[create] failed with: " + e ); + LogUtils.DEBUG( LogUtils.getTrace( e ) ); + result = new Any(new Type(Boolean.class), Boolean.FALSE); + + // throw new com.sun.star.reflection.InvocationTargetException( + // "Error creating script: " + e.getMessage()); + } + } + else if (aFunctionName.equals("Deletable")) + { + try + { + if ( container.deleteParcel(getName()) ) + { + result = new Any(new Type(Boolean.class), Boolean.TRUE); + } + else + { + result = new Any(new Type(Boolean.class), Boolean.FALSE); + } + } + catch (Exception e) + { + result = new Any(new Type(Boolean.class), Boolean.FALSE); + + // throw new com.sun.star.reflection.InvocationTargetException( + // "Error deleting parcel: " + e.getMessage()); + } + } + else if (aFunctionName.equals("Renamable")) + { + String newName = null; + try + { + + if (aParams == null || aParams.length < 1 || + AnyConverter.isString(aParams[0]) == false) + { + String prompt = "Enter new name for Library"; + String title = "Rename Library"; + + // try to get a DialogFactory instance, if it fails + // just use a Swing JOptionPane to prompt for the name + try + { + DialogFactory dialogFactory = + DialogFactory.getDialogFactory(); + + newName = dialogFactory.showInputDialog(title, prompt); + } + catch (Exception e) + { + newName = JOptionPane.showInputDialog(null, prompt, title, + JOptionPane.QUESTION_MESSAGE); + } + } + else { + newName = (String) AnyConverter.toString(aParams[0]); + } + container.renameParcel( getName(), newName ); + Parcel p = (Parcel)container.getByName( newName ); + if(browsenodes == null ) + { + getChildNodes(); + } + ScriptBrowseNode[] childNodes = (ScriptBrowseNode[])browsenodes.toArray(new ScriptBrowseNode[0]); + + for ( int index = 0; index < childNodes.length; index++ ) + { + childNodes[ index ].updateURI( p ); + } + result = new Any(new Type(XBrowseNode.class), this); + } + catch (Exception e) + { + result = new Any(new Type(Boolean.class), Boolean.FALSE); + + // throw new com.sun.star.reflection.InvocationTargetException( + // "Error renaming parcel: " + e.getMessage()); + } + } + + else { + throw new com.sun.star.lang.IllegalArgumentException( + "Function " + aFunctionName + " not supported."); + } + + return result; + } + + public void setValue(String aPropertyName, Object aValue) + throws com.sun.star.beans.UnknownPropertyException, + com.sun.star.script.CannotConvertException, + com.sun.star.reflection.InvocationTargetException + { + } + + public Object getValue(String aPropertyName) + throws com.sun.star.beans.UnknownPropertyException + { + return null; + } + + public boolean hasMethod(String aName) { + return false; + } + + public boolean hasProperty(String aName) { + return false; + } +} diff --git a/scripting/java/com/sun/star/script/framework/browse/PkgProviderBrowseNode.java b/scripting/java/com/sun/star/script/framework/browse/PkgProviderBrowseNode.java new file mode 100644 index 000000000000..7d3ef23a94be --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/browse/PkgProviderBrowseNode.java @@ -0,0 +1,65 @@ +/************************************************************************* + * + * 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.browse; + +import com.sun.star.uno.XComponentContext; + +import com.sun.star.script.XInvocation; + +import com.sun.star.script.browse.XBrowseNode; + +import com.sun.star.script.framework.provider.ScriptProvider; +import com.sun.star.script.framework.log.*; +import com.sun.star.script.framework.container.*; + + +public class PkgProviderBrowseNode extends ProviderBrowseNode + implements XBrowseNode, XInvocation +{ + + public PkgProviderBrowseNode( ScriptProvider provider, ParcelContainer container, XComponentContext xCtx ) { + super( provider, container, xCtx ); + LogUtils.DEBUG("*** PkgProviderBrowseNode ctor container name = " + container.getName()); + LogUtils.DEBUG("*** PkgProviderBrowseNode ctor container path = " + container.getParcelContainerDir()); + LogUtils.DEBUG("*** PkgProviderBrowseNode ctor, container has num parcels = " + container.getElementNames().length); + deletable = false; + editable = false; + creatable = false; + + } + + public String getName() { + String name = "Unknown"; + if ( container != null ) + { + name = container.getName(); + } + return name; + } + +} diff --git a/scripting/java/com/sun/star/script/framework/browse/ProviderBrowseNode.java b/scripting/java/com/sun/star/script/framework/browse/ProviderBrowseNode.java new file mode 100644 index 000000000000..99aa4e44e91a --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/browse/ProviderBrowseNode.java @@ -0,0 +1,291 @@ +/************************************************************************* + * + * 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.browse; + +import com.sun.star.lib.uno.helper.PropertySet; +import com.sun.star.uno.Any; +import com.sun.star.uno.AnyConverter; +import com.sun.star.uno.Type; +import com.sun.star.uno.XComponentContext; +import com.sun.star.uno.UnoRuntime; + +import com.sun.star.lang.XMultiComponentFactory; + +import com.sun.star.ucb.XSimpleFileAccess; + +import com.sun.star.beans.XIntrospectionAccess; +import com.sun.star.script.XInvocation; + +import com.sun.star.script.browse.XBrowseNode; +import com.sun.star.script.browse.BrowseNodeTypes; + +import com.sun.star.script.framework.provider.ScriptProvider; +import com.sun.star.script.framework.log.*; +import com.sun.star.script.framework.container.*; +import com.sun.star.script.framework.browse.DialogFactory; + +import java.util.*; +import javax.swing.JOptionPane; + +public class ProviderBrowseNode extends PropertySet + implements XBrowseNode, XInvocation +{ + protected ScriptProvider provider; + protected Collection browsenodes; + protected String name; + protected ParcelContainer container; + protected Parcel parcel; + protected XComponentContext m_xCtx; + + public boolean deletable = true; + public boolean creatable = true; + public boolean editable = false; + + public ProviderBrowseNode( ScriptProvider provider, ParcelContainer container, XComponentContext xCtx ) { + LogUtils.DEBUG("*** ProviderBrowseNode ctor"); + this.container = container; + this.name = this.container.getLanguage(); + this.provider = provider; + this.m_xCtx = xCtx; + + registerProperty("Deletable", new Type(boolean.class), + (short)0, "deletable"); + registerProperty("Creatable", new Type(boolean.class), + (short)0, "creatable"); + registerProperty("Editable", new Type(boolean.class), + (short)0, "editable"); + XSimpleFileAccess xSFA = null; + XMultiComponentFactory xFac = m_xCtx.getServiceManager(); + try + { + xSFA = ( XSimpleFileAccess) + UnoRuntime.queryInterface( XSimpleFileAccess.class, + xFac.createInstanceWithContext( + "com.sun.star.ucb.SimpleFileAccess", + xCtx ) ); + if ( container.isUnoPkg() || xSFA.isReadOnly( container.getParcelContainerDir() ) ) + { + deletable = false; + creatable = false; + } + } + // TODO propage errors + catch( com.sun.star.uno.Exception e ) + { + LogUtils.DEBUG("Caught exception in creation of ProviderBrowseNode "); + LogUtils.DEBUG( LogUtils.getTrace(e)); + + } + } + + public String getName() { + return name; + } + + public XBrowseNode[] getChildNodes() { + LogUtils.DEBUG("***** ProviderBrowseNode.getChildNodes()"); + if ( hasChildNodes() ) + { + // needs initialisation? + LogUtils.DEBUG("** ProviderBrowseNode.getChildNodes(), container is " + container ); + String[] parcels = container.getElementNames(); + browsenodes = new ArrayList( parcels.length ); + for ( int index = 0; index < parcels.length; index++ ) + { + try + { + XBrowseNode node = new ParcelBrowseNode( provider, container, parcels[ index ] ); + browsenodes.add( node ); + } + catch ( Exception e ) + { + LogUtils.DEBUG("*** Failed to create parcel node for " + parcels[ index ] ); + LogUtils.DEBUG( e.toString() ); + } + } + ParcelContainer[] packageContainers = container.getChildContainers(); + LogUtils.DEBUG("**** For container named " + container.getName() + " with root path " + container.getParcelContainerDir() + " has " + packageContainers.length + " child containers " ); + + for ( int i = 0; i < packageContainers.length; i++ ) + { + XBrowseNode node = new PkgProviderBrowseNode( provider, packageContainers[ i ], m_xCtx ); + browsenodes.add( node ); + } + } + else + { + LogUtils.DEBUG("*** No container available"); + return new XBrowseNode[0]; + } + return ( XBrowseNode[] )browsenodes.toArray( new XBrowseNode[0] ); + } + + public boolean hasChildNodes() { + boolean result = true; + + if ( container == null || + ( !container.hasElements() && + container.getChildContainers().length == 0 ) ) + { + result = false; + } + + LogUtils.DEBUG("***** ProviderBrowseNode.hasChildNodes(): " + + "name=" + name + + ", path=" + container.getParcelContainerDir() + + ", result=" + result ); + + return result; + } + + public short getType() { + return BrowseNodeTypes.CONTAINER; + } + + public String toString() + { + return getName(); + } + + // implementation of XInvocation interface + public XIntrospectionAccess getIntrospection() { + return null; + } + + public Object invoke(String aFunctionName, Object[] aParams, + short[][] aOutParamIndex, Object[][] aOutParam) + throws com.sun.star.lang.IllegalArgumentException, + com.sun.star.script.CannotConvertException, + com.sun.star.reflection.InvocationTargetException + { + // Initialise the out paramters - not used but prevents error in + // UNO bridge + aOutParamIndex[0] = new short[0]; + aOutParam[0] = new Object[0]; + + Any result = new Any(new Type(Boolean.class), Boolean.TRUE); + + if (aFunctionName.equals("Creatable")) + { + try + { + String name; + + if (aParams == null || aParams.length < 1 || + AnyConverter.isString(aParams[0]) == false) + { + String prompt = "Enter name for new Parcel"; + String title = "Create Parcel"; + + // try to get a DialogFactory instance, if it fails + // just use a Swing JOptionPane to prompt for the name + try + { + DialogFactory dialogFactory = + DialogFactory.getDialogFactory(); + + name = dialogFactory.showInputDialog(title, prompt); + } + catch (Exception e) + { + name = JOptionPane.showInputDialog(null, prompt, title, + JOptionPane.QUESTION_MESSAGE); + } + } + else { + name = (String) AnyConverter.toString(aParams[0]); + } + + if (name == null || name.equals("")) + { + result = new Any(new Type(Boolean.class), Boolean.FALSE); + } + else + { + + Object newParcel = container.createParcel( name ); + LogUtils.DEBUG("Parcel created " + name + " " + newParcel ); + if ( newParcel == null ) + { + result = new Any(new Type(Boolean.class), Boolean.FALSE); + } + else + { + ParcelBrowseNode parcel = new ParcelBrowseNode( provider, container, name ); + LogUtils.DEBUG("created parcel node "); + if ( browsenodes == null ) + { + browsenodes = new ArrayList( 5 ); + } + + browsenodes.add(parcel); + + + result = new Any(new Type(XBrowseNode.class), parcel); + } + } + } + catch (Exception e) + { + LogUtils.DEBUG("ProviderBrowseNode[create] failed with: " + e ); + LogUtils.DEBUG( LogUtils.getTrace( e ) ); + result = new Any(new Type(Boolean.class), Boolean.FALSE); + + // throw new com.sun.star.reflection.InvocationTargetException( + // "Error creating script: " + e.getMessage()); + } + } + else { + throw new com.sun.star.lang.IllegalArgumentException( + "Function " + aFunctionName + " not supported."); + } + + return result; + } + + public void setValue(String aPropertyName, Object aValue) + throws com.sun.star.beans.UnknownPropertyException, + com.sun.star.script.CannotConvertException, + com.sun.star.reflection.InvocationTargetException + { + } + + public Object getValue(String aPropertyName) + throws com.sun.star.beans.UnknownPropertyException + { + return null; + } + + public boolean hasMethod(String aName) { + return false; + } + + public boolean hasProperty(String aName) { + return false; + } +} diff --git a/scripting/java/com/sun/star/script/framework/browse/ScriptBrowseNode.java b/scripting/java/com/sun/star/script/framework/browse/ScriptBrowseNode.java new file mode 100644 index 000000000000..30c35105a9a0 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/browse/ScriptBrowseNode.java @@ -0,0 +1,335 @@ +/************************************************************************* + * + * 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.browse; + +import com.sun.star.script.browse.XBrowseNode; +import com.sun.star.script.browse.BrowseNodeTypes; +import com.sun.star.script.provider.XScriptContext; + +import com.sun.star.lib.uno.helper.PropertySet; +import com.sun.star.uno.AnyConverter; +import com.sun.star.uno.Any; +import com.sun.star.uno.Type; +import com.sun.star.uno.XComponentContext; +import com.sun.star.uno.UnoRuntime; + +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.ucb.XSimpleFileAccess; +import com.sun.star.beans.XIntrospectionAccess; +import com.sun.star.script.XInvocation; + +import com.sun.star.lang.NoSupportException; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.reflection.InvocationTargetException; +import com.sun.star.container.NoSuchElementException; +import com.sun.star.container.ElementExistException; + +import java.util.*; + +import com.sun.star.script.framework.log.LogUtils; +import com.sun.star.script.framework.provider.ScriptProvider; +import com.sun.star.script.framework.container.*; + +public class ScriptBrowseNode extends PropertySet + implements XBrowseNode, XInvocation +{ + private ScriptProvider provider; + + private Parcel parent; + private String name; + public String uri; + public String description; + public boolean editable = false; + public boolean deletable = false; + public boolean renamable = false; + + public ScriptBrowseNode( ScriptProvider provider, Parcel parent, + String name ) + { + this.provider = provider; + this.name = name; + this.parent = parent; + ScriptMetaData data = null; + XSimpleFileAccess xSFA = null; + XComponentContext xCtx = provider.getScriptingContext().getComponentContext(); + XMultiComponentFactory xFac = xCtx.getServiceManager(); + try + { + data = (ScriptMetaData)parent.getByName( name ); + xSFA = ( XSimpleFileAccess) + UnoRuntime.queryInterface( XSimpleFileAccess.class, + xFac.createInstanceWithContext( + "com.sun.star.ucb.SimpleFileAccess", + xCtx ) ); + } + + // TODO fix exception types to be caught here, should we rethrow? + catch ( Exception e ) + { + LogUtils.DEBUG("** caught exception getting script data for " + name + " ->" + e.toString() ); + } + + uri = data.getShortFormScriptURL(); + description = data.getDescription(); + + if (provider.hasScriptEditor() == true) + { + + this.editable = true; + try + { + if ( !parent.isUnoPkg() && + !xSFA.isReadOnly( parent.getPathToParcel() ) ) + { + this.deletable = true; + this.renamable = true; + } + } + // TODO propagate errors + catch ( Exception e ) + { + LogUtils.DEBUG("Caught exception in creation of ScriptBrowseNode"); + LogUtils.DEBUG( LogUtils.getTrace(e)); + } + + } + + registerProperty("Deletable", new Type(boolean.class), + (short)0, "deletable"); + registerProperty("Editable", new Type(boolean.class), + (short)0, "editable"); + registerProperty("Renamable", new Type(boolean.class), + (short)0, "renamable"); + registerProperty("URI", new Type(String.class), + (short)0, "uri"); + registerProperty("Description", new Type(String.class), + (short)0, "description"); + } + + + public String getName() { + return name; + } + + public XBrowseNode[] getChildNodes() { + return new XBrowseNode[0]; + } + + public boolean hasChildNodes() { + return false; + } + + public short getType() { + return BrowseNodeTypes.SCRIPT; + } + + public String toString() { + return getName(); + } + + public void updateURI( Parcel p ) { + parent = p; + ScriptMetaData data = null; + try + { + data = (ScriptMetaData)parent.getByName( name ); + } + + // TODO fix exception types to be caught here, should we rethrow? + catch ( Exception e ) + { + LogUtils.DEBUG("** caught exception getting script data for " + name + " ->" + e.toString() ); + } + uri = data.getShortFormScriptURL(); + } + // implementation of XInvocation interface + public XIntrospectionAccess getIntrospection() { + return null; + } + + public Object invoke(String aFunctionName, Object[] aParams, + short[][] aOutParamIndex, Object[][] aOutParam) + throws com.sun.star.lang.IllegalArgumentException, + com.sun.star.script.CannotConvertException, + com.sun.star.reflection.InvocationTargetException + { + // Initialise the out paramters - not used but prevents error in + // UNO bridge + aOutParamIndex[0] = new short[0]; + aOutParam[0] = new Object[0]; + + Any result = new Any(new Type(Boolean.class), Boolean.TRUE); + + if (aFunctionName.equals("Editable")) + { + if (!editable) + { + NoSupportException nse = new NoSupportException( + aFunctionName + " is not editable " ); + + throw new InvocationTargetException( + "Scripting framework error editing script", null, nse ); + } + + XScriptContext ctxt = provider.getScriptingContext(); + ScriptMetaData data = null; + try + { + data = (ScriptMetaData)parent.getByName( name ); + } + catch ( NoSuchElementException nse ) + { + throw new com.sun.star.lang.IllegalArgumentException( + name + " does not exist or can't be found " ); + } + catch ( com.sun.star.lang.WrappedTargetException wte ) + { + // rethrow + throw new InvocationTargetException( + "Scripting framework editing script ", + null, wte.TargetException ); + } + + provider.getScriptEditor().edit(ctxt, data); + } + else if (aFunctionName.equals("Deletable")) + { + if (!deletable) + { + NoSupportException nse = new NoSupportException( + aFunctionName + " is not supported for this node" ); + + throw new InvocationTargetException( + "Scripting framework error deleting script", null, nse ); + } + try + { + parent.removeByName( name ); + result = new Any(new Type(Boolean.class), Boolean.TRUE); + } + catch ( NoSuchElementException nse ) + { + throw new com.sun.star.lang.IllegalArgumentException( + name + " does not exist or can't be found " ); + } + catch ( WrappedTargetException wte ) + { + // rethrow + throw new InvocationTargetException( + "Scripting framework deleting script ", + null, wte.TargetException ); + } + + } + else if (aFunctionName.equals("Renamable")) + { + result = new Any(new Type(XBrowseNode.class), new XBrowseNode[0]); + if (!renamable) + { + NoSupportException nse = new NoSupportException( + aFunctionName + " is not supported for this node" ); + + throw new InvocationTargetException( + "Scripting framework error renaming script", null, nse ); + } + + try + { + String newName = (String) AnyConverter.toString(aParams[0]); + ScriptMetaData oldData = (ScriptMetaData)parent.getByName( name ); + oldData.loadSource(); + String oldSource = oldData.getSource(); + + LogUtils.DEBUG("Create renamed script"); + String languageName = + newName + "." + provider.getScriptEditor().getExtension(); + String language = provider.getName(); + + ScriptEntry entry = new ScriptEntry( + language, languageName, languageName, "", new HashMap() ); + + ScriptMetaData data = new ScriptMetaData( + parent, entry, oldSource ); + + parent.insertByName( languageName, data ); + + LogUtils.DEBUG("Now remove old script"); + parent.removeByName( name ); + + uri = data.getShortFormScriptURL(); + name = languageName; + result = new Any(new Type(XBrowseNode.class), this); + } + catch ( NoSuchElementException nse ) + { + throw new com.sun.star.lang.IllegalArgumentException( + name + " does not exist or can't be found " ); + } + catch ( ElementExistException eee ) + { + // rethrow + throw new InvocationTargetException( + "Scripting framework error renaming script ", + null, eee ); + } + catch ( WrappedTargetException wte ) + { + // rethrow + throw new InvocationTargetException( + "Scripting framework rename script ", + null, wte.TargetException ); + } + } + else { + throw new com.sun.star.lang.IllegalArgumentException( + "Function " + aFunctionName + " not supported."); + } + + return result; + } + + public void setValue(String aPropertyName, Object aValue) + throws com.sun.star.beans.UnknownPropertyException, + com.sun.star.script.CannotConvertException, + com.sun.star.reflection.InvocationTargetException + { + } + + public Object getValue(String aPropertyName) + throws com.sun.star.beans.UnknownPropertyException + { + return null; + } + + public boolean hasMethod(String aName) { + return false; + } + + public boolean hasProperty(String aName) { + return false; + } +} diff --git a/scripting/java/com/sun/star/script/framework/container/DeployedUnoPackagesDB.java b/scripting/java/com/sun/star/script/framework/container/DeployedUnoPackagesDB.java new file mode 100644 index 000000000000..abc28fb36b4f --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/container/DeployedUnoPackagesDB.java @@ -0,0 +1,231 @@ +/************************************************************************* + * + * 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.container; + +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.io.ByteArrayInputStream; + +import java.util.ArrayList; + +// import javax.xml.parsers.DocumentBuilderFactory; +// import javax.xml.parsers.DocumentBuilder; +// import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.*; + +public class DeployedUnoPackagesDB { + + // File name to be used for parcel descriptor files + private static final String + PARCEL_DESCRIPTOR_NAME = "unopkg-desc.xml"; + + // This is the default contents of a parcel descriptor to be used when + // creating empty descriptors + private static final byte[] EMPTY_DOCUMENT = + ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + + "<unopackages xmlns:unopackages=\"unopackages.dtd\">\n" + + "</unopackages>").getBytes(); + + private File file = null; + private Document document = null; + + public DeployedUnoPackagesDB() throws IOException { + ByteArrayInputStream bis = null; + try { + bis = new ByteArrayInputStream(EMPTY_DOCUMENT); + this.document = XMLParserFactory.getParser().parse(bis); + } + finally { + if (bis != null) + bis.close(); + } + } + + public DeployedUnoPackagesDB(Document document) { + this.document = document; + } + + public DeployedUnoPackagesDB(InputStream is) throws IOException { + this(XMLParserFactory.getParser().parse(is)); + } + + public String[] getDeployedPackages( String language ) + { + ArrayList packageUrls = new ArrayList(4); + Element main = document.getDocumentElement(); + Element root = null; + Element item; + int len = 0; + NodeList langNodes = null; + + if ((langNodes = main.getElementsByTagName("language")) != null && + (len = langNodes.getLength()) != 0) + { + for ( int i=0; i<len; i++ ) + { + Element e = (Element)langNodes.item( i ); + if ( e.getAttribute("value").equals(language) ) + { + root = e; + break; + } + } + } + if ( root != null ) + { + len = 0; + NodeList packages = null; + if ((packages = root.getElementsByTagName("package")) != null && + (len = packages.getLength()) != 0) + { + + for ( int i=0; i<len; i++ ) + { + + Element e = (Element)packages.item( i ); + packageUrls.add( e.getAttribute("value") ); + } + } + } + if ( !packageUrls.isEmpty() ) + { + return (String[])packageUrls.toArray( new String[0] ); + } + return new String[0]; + } + + public void write(OutputStream out) throws IOException { + XMLParserFactory.getParser().write(document, out); + } + + public Document getDocument() { + return document; + } + + + private void clearEntries() { + NodeList langNodes; + Element main = document.getDocumentElement(); + int len; + + if ((langNodes = document.getElementsByTagName("language")) != null && + (len = langNodes.getLength()) != 0) + { + for (int i = len - 1; i >= 0; i--) { + try { + main.removeChild(langNodes.item(i)); + } + catch (DOMException de) { + // ignore + } + } + } + } + + public boolean removePackage( String language, String url ) + { + Element main = document.getDocumentElement(); + Element langNode = null; + int len = 0; + NodeList langNodes = null; + boolean result = false; + if ((langNodes = main.getElementsByTagName("language")) != null && + (len = langNodes.getLength()) != 0) + { + for ( int i=0; i<len; i++ ) + { + Element e = (Element)langNodes.item( i ); + if ( e.getAttribute("value").equals(language) ) + { + langNode = e; + break; + } + } + } + if ( langNode != null ) + { + len = 0; + NodeList packages = null; + if ((packages = langNode.getElementsByTagName("package")) != null && + (len = packages.getLength()) != 0) + { + for ( int i=0; i<len; i++ ) + { + + Element e = (Element)packages.item( i ); + String value = e.getAttribute("value"); + + if ( value.equals(url) ) + { + langNode.removeChild( e ); + result = true; + break; + } + } + } + } + return result; + } + + public void addPackage(String language, String url ) { + Element main = document.getDocumentElement(); + Element langNode = null; + Element pkgNode = null; + + int len = 0; + NodeList langNodes = null; + + if ((langNodes = document.getElementsByTagName("language")) != null && + (len = langNodes.getLength()) != 0) + { + for ( int i=0; i<len; i++ ) + { + Element e = (Element)langNodes.item( i ); + if ( e.getAttribute("value").equals(language) ) + { + langNode = e; + break; + } + } + } + if ( langNode == null ) + { + langNode = document.createElement("language"); + langNode.setAttribute( "value", language ); + } + pkgNode = document.createElement("package"); + pkgNode.setAttribute( "value", url ); + + langNode.appendChild(pkgNode); + //add to the Top Element + main.appendChild(langNode); + } +} diff --git a/scripting/java/com/sun/star/script/framework/container/Parcel.java b/scripting/java/com/sun/star/script/framework/container/Parcel.java new file mode 100644 index 000000000000..40790eae6b28 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/container/Parcel.java @@ -0,0 +1,308 @@ +/************************************************************************* + * + * 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.container; +import com.sun.star.script.framework.log.*; +import com.sun.star.script.framework.io.*; +import com.sun.star.script.framework.provider.PathUtils; + +import com.sun.star.container.*; +import com.sun.star.uno.Type; +import com.sun.star.uno.UnoRuntime; + +import com.sun.star.ucb.XSimpleFileAccess; +import com.sun.star.ucb.XSimpleFileAccess2; +import java.io.*; + +public class Parcel implements XNameContainer +{ + protected ParcelDescriptor m_descriptor; + protected String name; + protected ParcelContainer parent; + protected XSimpleFileAccess m_xSFA; + public Parcel( XSimpleFileAccess xSFA, ParcelContainer parent, ParcelDescriptor desc, String parcelName ) + { + this( parent, desc, parcelName ); + this.m_xSFA = xSFA; + } + + public Parcel( ParcelContainer parent, ParcelDescriptor desc, String parcelName ) + { + this.parent = parent; + this.m_descriptor = desc; + this.name = parcelName; + } + + /** + * Tests if this <tt>Parcel</tt> is in an UNO package + * or within a sub package within an UNO package + * + * @return <tt>true</tt> if has parent <tt>false</tt> otherwise + */ + public boolean isUnoPkg() { return parent.isUnoPkg(); } + + public String getName() + { + return name; + } + public java.lang.Object getByName( String aName ) throws com.sun.star.container.NoSuchElementException, com.sun.star.lang.WrappedTargetException + { + LogUtils.DEBUG("** Parcel.getByName for " + aName ); + ScriptEntry script = null; + try + { + if ( m_descriptor != null && hasElements() ) + { + ScriptEntry[] scripts = m_descriptor.getScriptEntries(); + if ( scripts.length != 0 ) + { + for ( int index = 0; index < scripts.length; index++ ) + { + if ( scripts[ index ].getLanguageName().equals( aName ) ) + { + script = scripts[ index ]; + break; + } + } + } + } + } + // catch unknown or un-checked exceptions + catch ( Exception e ) + { + throw new com.sun.star.lang.WrappedTargetException( e.toString() ); + } + if ( script == null ) + { + LogUtils.DEBUG("No script for " + aName ); + throw new com.sun.star.container.NoSuchElementException("No script named " + aName ); + } + ScriptMetaData data = new ScriptMetaData( this, script, null ); + + LogUtils.DEBUG("returning date for " + aName ); + return data; + } + public String[] getElementNames() + { + String[] results = new String[0]; + if ( m_descriptor != null ) + { + ScriptEntry[] scripts = m_descriptor.getScriptEntries(); + results = new String[ scripts.length ]; + for ( int index = 0; index < scripts.length; index++ ) + { + results[ index ] = scripts[ index ].getLanguageName(); + } + } + return results; + } + public boolean hasByName( String aName ) + { + + boolean result = true; + Object containee = null; + try + { + containee = getByName( aName ); + if ( containee != null ) + { + result = true; + } + } + catch( Exception e ) + { + result = false; + } + return result; + } + + public com.sun.star.uno.Type getElementType() { + // TODO at the moment this returns void indicating + // type is unknown ( from UNO point of view this is correct ) + // but, maybe we want to have a private UNO interface + // + return new Type(); + } + + public boolean hasElements() + { + if ( m_descriptor != null && m_descriptor.getScriptEntries().length > 0 ) + { + return true; + } + return false; + } + + public void replaceByName( String aName, java.lang.Object aElement ) throws com.sun.star.lang.IllegalArgumentException, com.sun.star.container.NoSuchElementException, com.sun.star.lang.WrappedTargetException + { + // TODO check type of aElement + // if not ok, throw IllegalArgument + if ( m_descriptor != null ) + { + try + { + ScriptEntry script = (ScriptEntry)getByName( aName ); + if ( script != null ) + { + //m_descriptor.removeScriptEntry( script ); + // TODO needs to create source file ( if there is one ) + //m_descriptor.write(); + } + else + { + throw new com.sun.star.container.NoSuchElementException("No script named " + aName ); + } + + + } + // TO DO should catch specified exceptions + catch ( Exception e ) + { + throw new com.sun.star.lang.WrappedTargetException(); + } + + } + } + + // create + public void insertByName( String aName, java.lang.Object aElement ) throws com.sun.star.lang.IllegalArgumentException, ElementExistException, com.sun.star.lang.WrappedTargetException + { + // TODO check the type of aElement and throw# + // if not appropriate + try + { + if ( hasByName( aName ) ) + { + throw new ElementExistException( aName ); + } + ScriptMetaData script = (ScriptMetaData)aElement; + + if ( script.hasSource() ) + { + LogUtils.DEBUG("Inserting source: " + script.getSource()); + if ( !script.writeSourceFile() ) + { + throw new com.sun.star.lang.WrappedTargetException( "Failed to create source file " + script.getLanguageName() ); + } + } + m_descriptor.addScriptEntry( script ); + writeParcelDescriptor(); + } + catch ( Exception e ) + { + LogUtils.DEBUG("Failed to insert entry " + aName + ": " + e.getMessage()); + throw new com.sun.star.lang.WrappedTargetException( e.toString() ); + } + } + + + private void writeParcelDescriptor() + throws com.sun.star.ucb.CommandAbortedException, + com.sun.star.io.IOException, + com.sun.star.uno.Exception, java.io.IOException + { + String pathToDescriptor = PathUtils.make_url( + getPathToParcel(), ParcelDescriptor.PARCEL_DESCRIPTOR_NAME ); + + XSimpleFileAccess2 xSFA2 = ( XSimpleFileAccess2 ) + UnoRuntime.queryInterface( XSimpleFileAccess2.class, m_xSFA ); + + if ( xSFA2 != null ) + { + ByteArrayOutputStream bos = null; + ByteArrayInputStream bis = null; + XInputStreamImpl xis = null; + try + { + bos = new ByteArrayOutputStream( 1024 ); + m_descriptor.write( bos ); + bis = new ByteArrayInputStream( bos.toByteArray() ); + + xis = new XInputStreamImpl( bis ); + xSFA2.writeFile( pathToDescriptor, xis ); + } + finally + { + if (bos != null) bos.close(); + if (bis != null) bis.close(); + if (xis != null) xis.closeInput(); + } + } + } + + // delete + public void removeByName( String Name ) throws com.sun.star.container.NoSuchElementException, com.sun.star.lang.WrappedTargetException + { + try + { + ScriptMetaData script = null; + if ( ( script = (ScriptMetaData)getByName( Name ) ) != null ) + { +// if ( script.hasSource() ) + { + if ( !script.removeSourceFile() ) + { + LogUtils.DEBUG("** Parcel.removeByName Failed to remove script " + Name ); + throw new com.sun.star.lang.WrappedTargetException("Failed to remove script " + Name ); + } + LogUtils.DEBUG("** Parcel.removeByName have removed script source file " + Name ); + } + m_descriptor.removeScriptEntry( script ); + writeParcelDescriptor(); + + } + else + { + throw new com.sun.star.container.NoSuchElementException( "No script named " + Name ); + } + + } + catch ( Exception e ) + { + LogUtils.DEBUG("** Parcel.removeByName Exception: " + e ); + throw new com.sun.star.lang.WrappedTargetException( e.toString() ); + } + + } + // rename parcel + public void rename( String name ) throws com.sun.star.lang.WrappedTargetException + { + this.name = name; + } + public ParcelContainer getParent() { return parent; } + /** + * Returns the path of this <tt>Parcel</tt> + * + * @return <tt>String</tt> path to parcel + */ + public String getPathToParcel() + { + String path = parent.getParcelContainerDir() + "/" + name; + return path; + } + +} + diff --git a/scripting/java/com/sun/star/script/framework/container/ParcelContainer.java b/scripting/java/com/sun/star/script/framework/container/ParcelContainer.java new file mode 100644 index 000000000000..018f8baee687 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/container/ParcelContainer.java @@ -0,0 +1,746 @@ +/************************************************************************* + * + * 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.container; + +import com.sun.star.script.framework.log.*; +import com.sun.star.script.framework.io.*; +import com.sun.star.script.framework.provider.PathUtils; + +import com.sun.star.container.*; +import com.sun.star.uno.Type; +import com.sun.star.lang.*; +import com.sun.star.io.*; +import java.io.*; +import java.util.*; +import com.sun.star.ucb.XSimpleFileAccess; +import com.sun.star.ucb.XSimpleFileAccess2; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.uno.XComponentContext; +import com.sun.star.uno.UnoRuntime; + +import com.sun.star.uri.XUriReference; +import com.sun.star.uri.XUriReferenceFactory; +import com.sun.star.uri.XVndSunStarScriptUrl; + +/** + * The <code>ParcelContainer</code> object is used to store the + * ScripingFramework specific Libraries. + * + * @author + * @created + */ + +public class ParcelContainer implements XNameAccess +{ + protected String language; + protected String containerUrl; + protected Collection parcels = new ArrayList(10); + static protected XSimpleFileAccess m_xSFA; + protected XComponentContext m_xCtx; + private ParcelContainer parent = null; + private Collection childContainers = new ArrayList(10);; + private boolean isPkgContainer = false; + + /** + * Tests if this <tt>ParcelContainer</tt> represents an UNO package + * or sub package within an UNO package + * + * @return <tt>true</tt> if has parent <tt>false</tt> otherwise + */ + public boolean isUnoPkg() { return isPkgContainer; } + /** + * Tests if this <tt>ParcelContainer</tt> has a parent + * a parent. + * + * @return <tt>true</tt> if has parent <tt>false</tt> otherwise + */ + public boolean hasParent() + { + if ( parent == null ) + { + return false; + } + return true; + } + + /** + * Returns this <tt>ParcelContainer</tt>'s parent + * + * @return <tt>ParcelContainer</tt> if has parent null otherwise + */ + public ParcelContainer parent() + { + return parent; + } + + /** + * Returns all child <tt>ParcelContainer</tt> + * this instance of <tt>ParcelContainer</tt> + * + * @return a new array of ParcelContainers. A zero + * length array is returned if no child ParcelContainers. + */ + public ParcelContainer[] getChildContainers() + { + if ( childContainers.isEmpty() ) + { + return new ParcelContainer[0]; + } + return (ParcelContainer[]) childContainers.toArray( new ParcelContainer[0] ); + + } + /** + * Removes a child <tt>ParcelContainer</tt> + * from this instance. + * @param child <tt>ParcelContainer</tt> to be added. + * + * @return <tt>true</tt> if child successfully removed + */ + public boolean removeChildContainer( ParcelContainer child ) + { + return childContainers.remove( child ); + } + + /** + * Adds a new child <tt>ParcelContainer</tt> + * to this instance. + * @param child <tt>ParcelContainer</tt> to be added. + * + */ + public void addChildContainer( ParcelContainer child ) + { + childContainers.add( child ); + } + + /** + * Returns a child <tt>ParcelContainer</tt> whose location + * matches the <tt>location</tt> argument passed to this method. + * @param key the <tt>location</tt> which is to + * be matched. + * + * @return child <tt>ParcelContainer</tt> or <null> if none + * found. + */ + + public ParcelContainer getChildContainer( String key ) + { + ParcelContainer result = null; + Iterator iter = childContainers.iterator(); + while ( iter.hasNext() ) + { + ParcelContainer c = (ParcelContainer) iter.next(); + String location = ScriptMetaData.getLocationPlaceHolder( + c.containerUrl, c.getName()); + + if ( key.equals( location ) ) + { + result = c; + break; + } + } + return result; + } + + /** + * Returns a child <tt>ParcelContainer</tt> whose member + * <tt>containerUrl</tt> matches the <tt>containerUrl</tt> + * argument passed to this method. + * @param containerUrl the <tt>containerUrl</tt> which is to + * be matched. + * + * @return child <tt>ParcelContainer</tt> or <null> if none + * found. + */ + + public ParcelContainer getChildContainerForURL( String containerUrl ) + { + ParcelContainer result = null; + Iterator iter = childContainers.iterator(); + while ( iter.hasNext() ) + { + ParcelContainer c = (ParcelContainer) iter.next(); + if ( containerUrl.equals( c.containerUrl ) ) + { + result = c; + break; + } + } + return result; + } + + /** + * Returns Name of this container. Name of this <tt>ParcelContainer</tt> + * is determined from the <tt>containerUrl</tt> as the last portion + * of the URL after the last forward slash. + * @return name of <tt>ParcelContainer</tt> + * found. + */ + public String getName() + { + String name = null; + // TODO handler package ParcelContainer? + if ( !containerUrl.startsWith( "vnd.sun.star.tdoc:" ) ) + { + // return name + String decodedUrl = java.net.URLDecoder.decode( containerUrl ); + int indexOfSlash = decodedUrl.lastIndexOf( "/" ); + if ( indexOfSlash != -1 ) + { + name = decodedUrl.substring( indexOfSlash + 1 ); + } + } + else + { + name = "document"; + } + return name; + } + + /** + * Initializes a newly created <code>ParcelContainer</code> object. + * @param xCtx UNO component context + * @param containerUrl location of this container. + * @param language language for which entries are stored + * @return name of <tt>ParcelContainer</tt> + * @throws IllegalArgumentException + * @throws WrappedTargetException + */ + + public ParcelContainer( XComponentContext xCtx, String containerUrl, String language ) throws com.sun.star.lang.IllegalArgumentException, com.sun.star.lang.WrappedTargetException + + { + this( null, xCtx, containerUrl, language, true ); + } + + /** + * Initializes a newly created <code>ParcelContainer</code> object. + * @param xCtx UNO component context + * @param containerUrl location of this container. + * @param language language for which entries are stored + * @param loadParcels set to <tt>true</tt> if parcels are to be loaded + * on construction. + * @return name of <tt>ParcelContainer</tt> + * @throws IllegalArgumentException + * @throws WrappedTargetException + */ + public ParcelContainer( XComponentContext xCtx, String containerUrl, String language, boolean loadParcels ) throws com.sun.star.lang.IllegalArgumentException, com.sun.star.lang.WrappedTargetException + { + this( null, xCtx, containerUrl, language, loadParcels ); + } + + /** + * Initializes a newly created <code>ParcelContainer</code> object. + * @param parent parent ParcelContainer + * @param xCtx UNO component context + * @param containerUrl location of this container. + * @param language language for which entries are stored + * @param loadParcels set to <tt>true</tt> if parcels are to be loaded + * on construction. + * @return name of <tt>ParcelContainer</tt> + * @throws IllegalArgumentException + */ + + public ParcelContainer( ParcelContainer parent, XComponentContext xCtx, String containerUrl, String language, boolean loadParcels ) throws com.sun.star.lang.IllegalArgumentException, com.sun.star.lang.WrappedTargetException + + { + LogUtils.DEBUG("Creating ParcelContainer for " + containerUrl + " loadParcels = " + loadParcels + " language = " + language ); + this.m_xCtx = xCtx; + this.language = language; + this.parent = parent; + this.containerUrl = containerUrl; + + initSimpleFileAccess(); + boolean parentIsPkgContainer = false; + + if ( parent != null ) + { + parentIsPkgContainer = parent.isUnoPkg(); + } + + if ( containerUrl.endsWith("uno_packages") || parentIsPkgContainer ) + { + isPkgContainer = true; + } + + if ( loadParcels ) + { + loadParcels(); + } + } + + + public String getContainerURL() { return this.containerUrl; } + + private synchronized void initSimpleFileAccess() + { + if ( m_xSFA != null ) + { + return; + } + try + { + m_xSFA = ( XSimpleFileAccess )UnoRuntime.queryInterface( + XSimpleFileAccess.class, + m_xCtx.getServiceManager().createInstanceWithContext( + "com.sun.star.ucb.SimpleFileAccess", m_xCtx ) ); + } + catch ( Exception e ) + { + // TODO should throw + LogUtils.DEBUG("Error instantiating simplefile access "); + LogUtils.DEBUG( LogUtils.getTrace( e ) ); + } + } + + public String getParcelContainerDir() + { + // If this container does not represent an uno-package + // then then it is a document, user or share + // in each case the convention is to have a Scripts/[language] + // dir where scripts reside + if ( !isUnoPkg() ) + { + return PathUtils.make_url( containerUrl , "Scripts/" + language.toLowerCase() ); + } + return containerUrl; + } + public Object getByName( String aName ) throws com.sun.star.container.NoSuchElementException, WrappedTargetException + { + Parcel parcel = null; + try + { + if ( hasElements() ) + { + Iterator iter = parcels.iterator(); + while ( iter.hasNext() ) + { + Parcel parcelToCheck = (Parcel)iter.next(); + + if ( parcelToCheck.getName().equals( aName ) ) + { + parcel = parcelToCheck; + break; + } + } + } + } + catch ( Exception e) + { + throw new WrappedTargetException( e.toString() ); + } + if ( parcel == null ) + { + throw new com.sun.star.container.NoSuchElementException( "Macro Library " + aName + " not found" ); + } + return parcel; + } + public String[] getElementNames() + { + if ( hasElements() ) + { + Parcel[] theParcels = (Parcel[])parcels.toArray( new Parcel[0] ); + String[] names = new String[ theParcels.length ]; + for ( int count = 0; count < names.length; count++ ) + { + names[count] = theParcels[ count ].getName(); + } + return names; + } + + return new String[0]; + } + public boolean hasByName( String aName ) + { + boolean isFound = false; + try + { + if ( getByName( aName ) != null ) + { + isFound = true; + } + + } + catch ( Exception e ) + { + //TODO - handle trace + } + return isFound; + } + public Type getElementType() + { + return new Type(); + } + public boolean hasElements() + { + if ( parcels == null || parcels.isEmpty() ) + { + return false; + } + return true; + } + + private void loadParcels() throws com.sun.star.lang.IllegalArgumentException, com.sun.star.lang.WrappedTargetException + { + try + { + LogUtils.DEBUG("About to load parcels from " + containerUrl ); + if ( m_xSFA.isFolder( getParcelContainerDir() ) ) + { + LogUtils.DEBUG( getParcelContainerDir() + " is a folder " ); + String[] children = m_xSFA.getFolderContents( getParcelContainerDir(), true ); + parcels = new ArrayList(children.length); + for ( int i = 0; i < children.length; i++) + { + LogUtils.DEBUG("Processing " + children[ i ] ); + try + { + loadParcel( children[ i ] ); + } + catch (java.lang.Exception e) + { + // print an error message and move on to + // the next parcel + LogUtils.DEBUG("ParcelContainer.loadParcels caught " + e.getClass().getName() + " exception loading parcel " + children[i] + ": " + e.getMessage() ); + } + } + } + else + { + LogUtils.DEBUG(" ParcelCOntainer.loadParcels " + getParcelContainerDir() + " is not a folder "); + } + + } + catch ( com.sun.star.ucb.CommandAbortedException e ) + { + LogUtils.DEBUG("ParcelContainer.loadParcels caught exception processing folders for " + getParcelContainerDir() ); + LogUtils.DEBUG("TRACE: " + LogUtils.getTrace(e) ); + throw new com.sun.star.lang.WrappedTargetException( e.toString() ); + } + catch ( com.sun.star.uno.Exception e ) + { + LogUtils.DEBUG("ParcelContainer.loadParcels caught exception processing folders for " + getParcelContainerDir() ); + LogUtils.DEBUG("TRACE: " + LogUtils.getTrace(e) ); + throw new com.sun.star.lang.WrappedTargetException( e.toString() ); + } + } + + public XNameContainer createParcel(String name) throws ElementExistException, com.sun.star.lang.WrappedTargetException + { + Parcel p = null; + if ( hasByName( name ) ) + { + throw new ElementExistException( "Parcel " + name + " already exists" ); + } + String pathToParcel = PathUtils.make_url( getParcelContainerDir() , name ); + + try + { + LogUtils.DEBUG("ParcelContainer.createParcel, creating folder " + pathToParcel ); + m_xSFA.createFolder( pathToParcel ); + + LogUtils.DEBUG("ParcelContainer.createParcel, folder " + pathToParcel + " created "); + + ParcelDescriptor pd = new ParcelDescriptor(); + pd.setLanguage( language ); + String parcelDesc = PathUtils.make_url( pathToParcel, ParcelDescriptor.PARCEL_DESCRIPTOR_NAME ); + XSimpleFileAccess2 xSFA2 = ( XSimpleFileAccess2 ) + UnoRuntime.queryInterface( XSimpleFileAccess2.class, m_xSFA ); + if ( xSFA2 != null ) + { + LogUtils.DEBUG("createParcel() Using XSIMPLEFILEACCESS2 " + parcelDesc ); + ByteArrayOutputStream bos = new ByteArrayOutputStream( 1024 ); + pd.write( bos ); + bos.close(); + ByteArrayInputStream bis = new ByteArrayInputStream( bos.toByteArray() ); + XInputStreamImpl xis = new XInputStreamImpl( bis ); + xSFA2.writeFile( parcelDesc, xis ); + xis.closeInput(); + p = loadParcel( pathToParcel ); + } + } + catch ( Exception e ) + { + + LogUtils.DEBUG("createParcel() Exception while attempting to create = " + name ); + throw new com.sun.star.lang.WrappedTargetException( e.toString() ); + } + return p; + } + + public Parcel loadParcel( String parcelUrl ) throws com.sun.star.lang.WrappedTargetException, com.sun.star.lang.IllegalArgumentException + { + + String name = null; + + String parcelDescUrl = PathUtils.make_url( parcelUrl, ParcelDescriptor.PARCEL_DESCRIPTOR_NAME ); + Parcel parcel = null; + + XInputStream xis = null; + InputStream is = null; + + try + { + if ( m_xSFA.exists( parcelDescUrl ) ) + { + LogUtils.DEBUG("ParcelContainer.loadParcel opening " + parcelDescUrl ); + xis = m_xSFA.openFileRead( parcelDescUrl ); + is = new XInputStreamWrapper( xis ); + + ParcelDescriptor pd = new ParcelDescriptor(is) ; + try + { + is.close(); + is = null; + } + catch ( Exception e ) + { + LogUtils.DEBUG("ParcelContainer.loadParcel Exception when closing stream for " + parcelDescUrl + " :" + e ); + } + LogUtils.DEBUG("ParcelContainer.loadParcel closed " + parcelDescUrl ); + if ( !pd.getLanguage().equals( language ) ) + { + LogUtils.DEBUG("ParcelContainer.loadParcel Language of Parcel does not match this container "); + return null; + } + LogUtils.DEBUG("Processing " + parcelDescUrl + " closed " ); + + int indexOfSlash = parcelUrl.lastIndexOf("/"); + name = parcelUrl.substring( indexOfSlash + 1 ); + + parcel = new Parcel( m_xSFA, this, pd, name ); + + LogUtils.DEBUG(" ParcelContainer.loadParcel created parcel for " + parcelDescUrl + " for language " + language ); + parcels.add( parcel ); + } + else + { + throw new java.io.IOException( parcelDescUrl + " does NOT exist!"); + } + } + catch ( com.sun.star.ucb.CommandAbortedException e ) + { + + LogUtils.DEBUG("loadParcel() Exception while accessing filesystem url = " + parcelDescUrl + e ); + throw new com.sun.star.lang.WrappedTargetException( e.toString() ); + } + catch ( java.io.IOException e ) + { + LogUtils.DEBUG("ParcelContainer.loadParcel() caught IOException while accessing " + parcelDescUrl + ": " + e ); + throw new com.sun.star.lang.WrappedTargetException( e.toString() ); + } + catch ( com.sun.star.uno.Exception e ) + { + + LogUtils.DEBUG("loadParcel() Exception while accessing filesystem url = " + parcelDescUrl + e ); + throw new com.sun.star.lang.WrappedTargetException( e.toString() ); + } + + finally + { + if ( is != null ) + { + try + { + is.close(); // is will close xis + } + catch ( Exception ignore ) + { + } + } + else if ( xis != null ) + { + try + { + xis.closeInput(); + } + catch ( Exception ignore ) + { + } + } + } + return parcel; + } + public void renameParcel(String oldName, String newName) throws com.sun.star.container.NoSuchElementException, com.sun.star.lang.WrappedTargetException + { + LogUtils.DEBUG(" ** ParcelContainer Renaming parcel " + oldName + " to " + newName ); + LogUtils.DEBUG(" ** ParcelContainer is " + this ); + Parcel p = (Parcel)getByName( oldName ); + if ( p == null ) + { + throw new com.sun.star.container.NoSuchElementException( "No parcel named " + oldName ); + } + String oldParcelDirUrl = PathUtils.make_url( getParcelContainerDir(), + oldName ); + String newParcelDirUrl = PathUtils.make_url( getParcelContainerDir(), + newName ); + try + { + if (!m_xSFA.isFolder( oldParcelDirUrl ) ) + { + Exception e = new com.sun.star.io.IOException("Invalid Parcel directory: " + oldName ); + throw new com.sun.star.lang.WrappedTargetException( e.toString() ); + } + LogUtils.DEBUG(" ** ParcelContainer Renaming folder " + oldParcelDirUrl + " to " + newParcelDirUrl ); + m_xSFA.move( oldParcelDirUrl, newParcelDirUrl ); + } + catch ( com.sun.star.ucb.CommandAbortedException ce ) + { + LogUtils.DEBUG(" ** ParcelContainer Renaming failed with " + ce ); + throw new com.sun.star.lang.WrappedTargetException( ce.toString() ); + } + catch ( com.sun.star.uno.Exception e ) + { + LogUtils.DEBUG(" ** ParcelContainer Renaming failed with " + e ); + throw new com.sun.star.lang.WrappedTargetException( e.toString() ); + } + + p.rename( newName ); + } + // removes but doesn't physically delele parcel from container + public boolean removeParcel(String name) throws com.sun.star.container.NoSuchElementException, com.sun.star.lang.WrappedTargetException + { + boolean result = false; + Parcel p = (Parcel)getByName( name ); + if ( p == null ) + { + throw new com.sun.star.container.NoSuchElementException("No parcel named " + name ); + } + + result = parcels.remove( p ); + return result; + } + public boolean deleteParcel(String name) throws com.sun.star.container.NoSuchElementException, com.sun.star.lang.WrappedTargetException + { + LogUtils.DEBUG( "deleteParcel for containerURL " + containerUrl + " name = " + name + " Langueg = " + language ); + boolean result = false; + + Parcel p = (Parcel)getByName( name ); + if ( p == null ) + { + throw new com.sun.star.container.NoSuchElementException("No parcel named " + name ); + } + + try + { + String pathToParcel = PathUtils.make_url( getParcelContainerDir(), name ); + m_xSFA.kill( pathToParcel ); + } + catch( Exception e ) + { + LogUtils.DEBUG("Error deleteing parcel " + name ); + throw new com.sun.star.lang.WrappedTargetException( e.toString() ); + } + + result = parcels.remove( p ); + return result; + } + + public String getLanguage() { return language; } + + public ScriptMetaData findScript( ParsedScriptUri parsedUri ) throws com.sun.star.container.NoSuchElementException, com.sun.star.lang.WrappedTargetException + { + ScriptMetaData scriptData = null; + Parcel p = null; + p = (Parcel)getByName( parsedUri.parcel); + scriptData = (ScriptMetaData)p.getByName( parsedUri.function); + LogUtils.DEBUG("** found script data for " + parsedUri.function + " script is " + scriptData ); + return scriptData; + + } +public ParsedScriptUri parseScriptUri( String scriptURI ) throws com.sun.star.lang.IllegalArgumentException +{ + + XMultiComponentFactory xMcFac = null; + XUriReferenceFactory xFac = null; + + try + { + xMcFac = m_xCtx.getServiceManager(); + xFac = ( XUriReferenceFactory ) + UnoRuntime.queryInterface( XUriReferenceFactory.class, + xMcFac.createInstanceWithContext( + "com.sun.star.uri.UriReferenceFactory", m_xCtx ) ); + } + catch( com.sun.star.uno.Exception e ) + { + LogUtils.DEBUG("Problems parsing URL:" + e.toString() ); + throw new com.sun.star.lang.IllegalArgumentException( "Problems parsing URL reason: " + e.toString() ); + } + if ( xFac == null ) + { + LogUtils.DEBUG("Failed to create UrlReference factory"); + throw new com.sun.star.lang.IllegalArgumentException( "Failed to create UrlReference factory for url " + scriptURI ); + } + + XUriReference uriRef = xFac.parse( scriptURI ); + XVndSunStarScriptUrl sfUri = ( XVndSunStarScriptUrl ) + UnoRuntime.queryInterface( XVndSunStarScriptUrl.class, uriRef ); + + if ( sfUri == null ) + { + LogUtils.DEBUG("Failed to parse url"); + throw new com.sun.star.lang.IllegalArgumentException( "Failed to parse url " + scriptURI ); + } + + ParsedScriptUri parsedUri = new ParsedScriptUri(); + // parse language + parsedUri.language = sfUri.getParameter("language"); + parsedUri.function= sfUri.getName(); + parsedUri.parcel = ""; + + // parse parcel name; + StringTokenizer tokenizer = new StringTokenizer( parsedUri.function, "." ); + + if ( tokenizer.hasMoreElements() ) + { + parsedUri.parcel = (String)tokenizer.nextElement(); + LogUtils.DEBUG("** parcelName = " + parsedUri.parcel ); + } + + if ( parsedUri.function != null && ( parsedUri.function.length() > 0 ) ) + { + // strip out parcel name + parsedUri.function = parsedUri.function.substring( parsedUri.parcel.length() + 1); + } + + // parse location + parsedUri.location = sfUri.getParameter("location"); + + // TODO basic sanity check on language, location, functioname, parcel + // should be correct e.g. verified by MSP and LangProvider by the + // time its got to here + + LogUtils.DEBUG("** location = " + parsedUri.location + + "\nfunction = " + parsedUri.function + + "\nparcel = " + parsedUri.parcel + + "\nlocation = " + parsedUri.location ); + return parsedUri; +} + + +} diff --git a/scripting/java/com/sun/star/script/framework/container/ParcelDescriptor.java b/scripting/java/com/sun/star/script/framework/container/ParcelDescriptor.java new file mode 100644 index 000000000000..b78f07079f0c --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/container/ParcelDescriptor.java @@ -0,0 +1,450 @@ +/************************************************************************* + * + * 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.container; + +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.FileNotFoundException; +import java.io.ByteArrayInputStream; + +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Enumeration; +import java.util.Iterator; + +// import javax.xml.parsers.DocumentBuilderFactory; +// import javax.xml.parsers.DocumentBuilder; +// import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.*; + +public class ParcelDescriptor { + + // File name to be used for parcel descriptor files + public static final String + PARCEL_DESCRIPTOR_NAME = "parcel-descriptor.xml"; + + // Collection of all ParcelDescriptor created for files + private static final Map PARCEL_DESCRIPTOR_MAP = new HashMap(5); + + // This is the default contents of a parcel descriptor to be used when + // creating empty descriptors + private static final byte[] EMPTY_DOCUMENT = + ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + + "<parcel xmlns:parcel=\"scripting.dtd\" language=\"Java\">\n" + + "</parcel>").getBytes(); + + private File file = null; + private Document document = null; + private String language = null; + private Map languagedepprops = new Hashtable(3); + + public static synchronized void removeParcelDescriptor(File parent) { + File path = new File(parent, PARCEL_DESCRIPTOR_NAME); + PARCEL_DESCRIPTOR_MAP.remove(path); + } + + public static synchronized void renameParcelDescriptor(File oldFile, File newFile) { + File oldPath = new File(oldFile, PARCEL_DESCRIPTOR_NAME); + ParcelDescriptor pd = (ParcelDescriptor)PARCEL_DESCRIPTOR_MAP.get(oldPath); + if(pd != null) { + PARCEL_DESCRIPTOR_MAP.remove(oldPath); + File newPath = new File(newFile, PARCEL_DESCRIPTOR_NAME); + pd.file = newPath; + PARCEL_DESCRIPTOR_MAP.put(newPath, pd); + } + } + + // returns the ParcelDescriptor in the corresponding directory + // returns null if no ParcelDescriptor is found in the directory + public static synchronized ParcelDescriptor + getParcelDescriptor(File parent) { + + File path = new File(parent, PARCEL_DESCRIPTOR_NAME); + ParcelDescriptor pd = (ParcelDescriptor)PARCEL_DESCRIPTOR_MAP.get(path); + + if (pd == null && path.exists()) { + try { + pd = new ParcelDescriptor(path); + } + catch (IOException ioe) { + return null; + } + PARCEL_DESCRIPTOR_MAP.put(path, pd); + } + return pd; + } + + // returns a ParcelDescriptor for the corresponding directory + // if no ParcelDescriptor exists, one is created + public static synchronized ParcelDescriptor + createParcelDescriptor(File parent) throws IOException { + + ParcelDescriptor pd = getParcelDescriptor(parent); + + if (pd == null) { + if (parent == null || !parent.exists() || !parent.isDirectory()) { + throw new IOException("Cannot create Parcel Descriptor"); + } + + File path = new File(parent, PARCEL_DESCRIPTOR_NAME); + pd = new ParcelDescriptor(path); + PARCEL_DESCRIPTOR_MAP.put(path, pd); + } + return pd; + } + + public ParcelDescriptor() throws IOException { + ByteArrayInputStream bis = null; + try { + bis = new ByteArrayInputStream(EMPTY_DOCUMENT); + this.document = XMLParserFactory.getParser().parse(bis); + } + finally { + if (bis != null) + bis.close(); + } + } + + public ParcelDescriptor(Document document) { + this.document = document; + initLanguageProperties(); + } + + public ParcelDescriptor(InputStream is) throws IOException { + this(XMLParserFactory.getParser().parse(is)); + } + + public ParcelDescriptor(File file) throws IOException { + this(file, "Java"); + } + + public ParcelDescriptor(File file, String language) throws IOException { + this.file = file; + + if (file.exists()) { + FileInputStream fis = null; + try { + fis = new FileInputStream(file); + this.document = XMLParserFactory.getParser().parse(fis); + } + finally { + if (fis != null) + fis.close(); + } + } + else { + ByteArrayInputStream bis = null; + try { + bis = new ByteArrayInputStream(EMPTY_DOCUMENT); + this.document = XMLParserFactory.getParser().parse(bis); + } + finally { + if (bis != null) + bis.close(); + } + setLanguage(language); + } + initLanguageProperties(); + } + + public void write(File file) throws IOException { + FileOutputStream fos = new FileOutputStream(file); + XMLParserFactory.getParser().write(document, fos); + fos.close(); + } + + public void write() throws IOException { + if (file == null) + throw new FileNotFoundException("No file specified"); + + write(file); + } + + public void write(OutputStream out) throws IOException { + XMLParserFactory.getParser().write(document, out); + } + + public Document getDocument() { + return document; + } + + public String getLanguage() { + if (language == null) { + if (document != null) { + Element e = document.getDocumentElement(); + language = e.getAttribute("language"); + } + } + return language; + } + + public void setLanguage(String language) { + this.language = language; + + if (document != null) { + try { + Element e = document.getDocumentElement(); + e.setAttribute("language", language); + } + catch (DOMException de) { + } + } + } + + public ScriptEntry[] getScriptEntries() { + ArrayList scripts = new ArrayList(); + NodeList scriptNodes; + int len; + + if (document == null || + (scriptNodes = document.getElementsByTagName("script")) == null || + (len = scriptNodes.getLength()) == 0) + return new ScriptEntry[0]; + + for (int i = 0; i < len; i++) { + String language, languagename, logicalname, description = ""; + Map langProps = new HashMap(); + NodeList nl; + Element tmp; + + Element scriptElement = (Element)scriptNodes.item(i); + language = scriptElement.getAttribute("language"); + + nl = scriptElement.getElementsByTagName("logicalname"); + if (nl == null) + logicalname = ""; + else { + tmp = (Element)nl.item(0); + logicalname = tmp.getAttribute("value"); + } + + // get the text of the description element + nl = scriptElement.getElementsByTagName("locale"); + if (nl != null) + { + nl = nl.item(0).getChildNodes(); + if (nl != null) + { + for (int j = 0 ; j < nl.getLength(); j++) + { + if (nl.item(j).getNodeName().equals("description")) + { + CharacterData cd = + (CharacterData)nl.item(j).getFirstChild(); + description = cd.getData().trim(); + } + } + } + } + + nl = scriptElement.getElementsByTagName("functionname"); + if (nl == null) { + languagename = ""; + } else { + tmp = (Element)nl.item(0); + languagename = tmp.getAttribute("value"); + } + nl = scriptElement.getElementsByTagName("languagedepprops"); + if ( nl != null && nl.getLength() > 0 ) + { + + NodeList props = ((Element)nl.item(0)).getElementsByTagName("prop"); + if ( props != null ) + { + for ( int j=0; j < props.getLength(); j++ ) + { + tmp = (Element)props.item(j); + String key = tmp.getAttribute("name"); + String val = tmp.getAttribute("value"); + langProps.put( key,val ); + } + } + } + ScriptEntry entry = new ScriptEntry(language, languagename, logicalname, "",langProps, description); + scripts.add(entry); + } + return (ScriptEntry[])scripts.toArray(new ScriptEntry[0]); + } + + public void setScriptEntries(ScriptEntry[] scripts) { + clearEntries(); + for (int i = 0; i < scripts.length; i++) + addScriptEntry(scripts[i]); + } + + public void setScriptEntries(Enumeration scripts) { + clearEntries(); + while (scripts.hasMoreElements()) + addScriptEntry((ScriptEntry) scripts.nextElement()); + } + + public String getLanguageProperty(String name) { + return (String)languagedepprops.get(name); + } + + public void setLanguageProperty(String name, String value) { + languagedepprops.put(name, value); + setScriptEntries(getScriptEntries()); + } + + private void initLanguageProperties() { + NodeList nl = document.getElementsByTagName("languagedepprops"); + int len; + + if (nl != null && (len = nl.getLength()) != 0) { + + for (int i = 0; i < len; i++) { + Element e = (Element)nl.item(i); + NodeList nl2 = e.getElementsByTagName("prop"); + int len2; + + if (nl2 != null && (len2 = nl2.getLength()) != 0) { + for (int j = 0; j < len2; j++) { + Element e2 = (Element)nl2.item(j); + + String name = e2.getAttribute("name"); + String value = e2.getAttribute("value"); + + if (getLanguageProperty(name) == null) { + languagedepprops.put(name, value); + } + } + } + } + } + } + + private void clearEntries() { + NodeList scriptNodes; + Element main = document.getDocumentElement(); + int len; + + if ((scriptNodes = document.getElementsByTagName("script")) != null && + (len = scriptNodes.getLength()) != 0) + { + for (int i = len - 1; i >= 0; i--) { + try { + main.removeChild(scriptNodes.item(i)); + } + catch (DOMException de) { + // ignore + } + } + } + } + + public void removeScriptEntry(ScriptEntry script) { + NodeList scriptNodes; + Element main = document.getDocumentElement(); + int len; + + if ((scriptNodes = document.getElementsByTagName("script")) != null && + (len = scriptNodes.getLength()) != 0) + { + for (int i = len - 1; i >= 0; i--) { + try { + Element scriptElement = (Element)scriptNodes.item(i); + String languagename = ""; + + NodeList nl = + scriptElement.getElementsByTagName("functionname"); + if (nl == null) { + continue; + } else { + Element tmp = (Element)nl.item(0); + languagename = tmp.getAttribute("value"); + } + + if (languagename.equals(script.getLanguageName())) { + main.removeChild(scriptElement); + } + } + catch (DOMException de) { + // ignore + } + } + } + } + + public void addScriptEntry(ScriptEntry script) { + Element main = document.getDocumentElement(); + Element root, item, tempitem; + + root = document.createElement("script"); + root.setAttribute("language", script.getLanguage()); + + item = document.createElement("locale"); + item.setAttribute("lang", "en"); + tempitem = document.createElement("displayname"); + tempitem.setAttribute("value", script.getLogicalName()); + item.appendChild(tempitem); + + tempitem = document.createElement("description"); + String description = script.getDescription(); + if (description == null || description.equals("")) + { + description = script.getLogicalName(); + } + tempitem.appendChild(document.createTextNode(description)); + item.appendChild(tempitem); + + root.appendChild(item); + + item = document.createElement("logicalname"); + item.setAttribute("value", script.getLogicalName()); + root.appendChild(item); + + item = document.createElement("functionname"); + item.setAttribute("value", script.getLanguageName()); + root.appendChild(item); + + if (languagedepprops != null && languagedepprops.size() != 0) { + String key; + item = document.createElement("languagedepprops"); + + Iterator iter = languagedepprops.keySet().iterator(); + while (iter.hasNext()) { + tempitem = document.createElement("prop"); + key = (String)iter.next(); + tempitem.setAttribute("name", key); + tempitem.setAttribute("value", (String)languagedepprops.get(key)); + item.appendChild(tempitem); + } + root.appendChild(item); + } + + //add to the Top Element + main.appendChild(root); + } +} diff --git a/scripting/java/com/sun/star/script/framework/container/ParsedScriptUri.java b/scripting/java/com/sun/star/script/framework/container/ParsedScriptUri.java new file mode 100644 index 000000000000..0a8febd8cdc6 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/container/ParsedScriptUri.java @@ -0,0 +1,36 @@ +/************************************************************************* +* + * 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.container; + +public class ParsedScriptUri +{ + public String language; + public String location; + public String function; + public String parcel; +} + diff --git a/scripting/java/com/sun/star/script/framework/container/ScriptEntry.java b/scripting/java/com/sun/star/script/framework/container/ScriptEntry.java new file mode 100644 index 000000000000..a888a73c8f3b --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/container/ScriptEntry.java @@ -0,0 +1,128 @@ +/************************************************************************* + * + * 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.container; +import java.util.Map; +import java.util.HashMap; +public class ScriptEntry implements Cloneable { + + private String language; + private String languagename; + private String location; + private String logicalname = ""; + private String description = ""; + + private Map languagedepprops; + + public ScriptEntry(String language, String languagename, + String logicalname, String location) { + this.language = language; + this.languagename = languagename; + // logical name/ function name concept + // needs to be reworked, in meantime + // function name ( from xml ) will be used + // as logical name also + this.logicalname = languagename; + this.location = location; + this.languagedepprops = new HashMap(); + } + + public ScriptEntry(ScriptEntry entry) + { + this.language = entry.language; + this.languagename = entry.languagename; + this.logicalname = entry.languagename; + this.location = entry.location; + this.languagedepprops = entry.languagedepprops; + this.description = entry.description; + } + + public ScriptEntry(String language, String languagename, + String logicalname, String location, Map languagedepprops) { + this( language, languagename, logicalname, location ); + this.languagedepprops = languagedepprops; + } + + public ScriptEntry(String language, String languagename, + String logicalname, String location, + Map languagedepprops, String description) { + this( language, languagename, logicalname, location ); + this.languagedepprops = languagedepprops; + this.description = description; + } + + public ScriptEntry(String languagename, String location) { + this("Java", languagename, languagename, location); + } + + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + public boolean equals(ScriptEntry other) { + if (language.equals(other.getLanguage()) && + languagename.equals(other.getLanguageName()) && + logicalname.equals(other.getLogicalName()) && + languagedepprops.equals(other.getLanguageProperties()) && + location.equals(other.getLocation())) + return true; + return false; + } + + public Map getLanguageProperties() + { + return languagedepprops; + } + + public String getLanguageName() { + return languagename; + } + + public String getLogicalName() { + return logicalname; + } + + public void setLogicalName(String name) { + logicalname = name; + } + + public String getLanguage() { + return language; + } + + public String getLocation() { + return location; + } + + public String getDescription() { + return description; + } + + public String toString() { + return "\nLogicalName = " + logicalname + "\nLanguageName = " + languagename + "\nLocation = " + location + "\nLanguaguageProperties = " + languagedepprops; + } +} diff --git a/scripting/java/com/sun/star/script/framework/container/ScriptMetaData.java b/scripting/java/com/sun/star/script/framework/container/ScriptMetaData.java new file mode 100644 index 000000000000..e7007972936b --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/container/ScriptMetaData.java @@ -0,0 +1,410 @@ +/************************************************************************* + * + * 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.container; + +import java.net.URL; + +import java.io.ByteArrayInputStream; + +import java.util.Vector; +import java.util.StringTokenizer; + +import java.io.InputStream; +import java.io.OutputStream; + +import com.sun.star.script.framework.log.LogUtils; + +import com.sun.star.script.framework.provider.PathUtils; + +import com.sun.star.script.framework.io.XInputStreamImpl; + +import com.sun.star.script.framework.container.ScriptEntry; +import com.sun.star.script.framework.container.Parcel; + +import com.sun.star.script.framework.io.UCBStreamHandler; + +import com.sun.star.ucb.XSimpleFileAccess2; + +import com.sun.star.uno.UnoRuntime; + +public class ScriptMetaData extends ScriptEntry implements Cloneable { + private boolean hasSource = false; + private String locationPlaceHolder = ""; + private String source; + private Parcel parent; + + + public ScriptMetaData( Parcel parent, ScriptEntry entry, + String source ) + { + super( entry ); + this.parent = parent; + if ( source != null ) + { + this.hasSource = true; + this.source = source; + } + + } + + public boolean hasSource() + { + return hasSource; + } + public String getSource() + { + + if ( source !=null && hasSource ) + { + return source; + } + else + { + return null; + } + } + + public byte[] getSourceBytes() + { + if ( source !=null && hasSource ) + { + return source.getBytes(); + } + else + { + return null; + } + + } + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + public boolean equals(ScriptMetaData other) { + if (super.equals(other) && + hasSource == other.hasSource() ) + { + return true; + } + return false; + } + + public String getScriptFullURL() + { + String url = "vnd.sun.star.script:" + parent.getName() + "." + getLanguageName() + + "?" + "language=" + getLanguage() + + "&location=" + getParcelLocation(); + return url; + } + + public String getShortFormScriptURL() + { + String url = "vnd.sun.star.script:" + parent.getName() + "." + getLanguageName() + + "?" + "language=" + getLanguage() + + "&location=" + getLocationPlaceHolder(); + return url; + } + + // TODO probably should be private should not be necessary + // to be exposed at all + + private static final String SHARE = + "vnd.sun.star.expand:${$BRAND_BASE_DIR/program/" + + PathUtils.BOOTSTRAP_NAME + + "::BaseInstallation}/share"; + + private static final String USER = + "vnd.sun.star.expand:${$BRAND_BASE_DIR/program/" + + PathUtils.BOOTSTRAP_NAME + + "::UserInstallation}/user"; + + private static final String UNO_USER_PACKAGES1 = + "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE"; + + private static final String UNO_USER_PACKAGES2 = + USER + "/uno_packages"; + + private static final String UNO_SHARED_PACKAGES1 = + "$UNO_SHARED_PACKAGES_CACHE"; + + private static final String UNO_SHARED_PACKAGES2 = + SHARE + "/uno_packages"; + + public static String getLocationPlaceHolder(String url, String pkgname) + { + String result = "Unknown"; + + if ( url.indexOf(UNO_USER_PACKAGES1) > -1 || + url.indexOf(UNO_USER_PACKAGES2) > -1 ) + { + result = PathUtils.make_url( "user:uno_packages", pkgname ); + } + else if ( url.indexOf(UNO_SHARED_PACKAGES1) > -1 || + url.indexOf(UNO_SHARED_PACKAGES2) > -1 ) + { + result = PathUtils.make_url( "share:uno_packages", pkgname ); + } + else if ( url.indexOf(SHARE) == 0 ) + { + result = "share"; + } + else if ( url.indexOf(USER) == 0 ) + { + result = "user"; + } + else if ( url.indexOf("vnd.sun.star.tdoc:") == 0 ) + { + result = "document"; + } + return result; + } + + public String getLocationPlaceHolder() + { + String placeHolder = "Unknown"; + String pathToParcel = parent.getPathToParcel(); + + if ( pathToParcel.indexOf(UNO_USER_PACKAGES1) > -1 || + pathToParcel.indexOf(UNO_USER_PACKAGES2) > -1 ) + { + // its a package + placeHolder = "user:uno_packages"; + String unoPkg = parent.parent.getName(); + if ( unoPkg != null ) + { + placeHolder = PathUtils.make_url( placeHolder, unoPkg ); + } + } + else if ( pathToParcel.indexOf(UNO_SHARED_PACKAGES1) > -1 || + pathToParcel.indexOf(UNO_SHARED_PACKAGES2) > -1 ) + { + //its a package + placeHolder = "share:uno_packages"; + String unoPkg = parent.parent.getName(); + if ( unoPkg != null ) + { + placeHolder = PathUtils.make_url( placeHolder, unoPkg ); + } + } + else if ( pathToParcel.indexOf(SHARE) == 0 ) + { + placeHolder = "share"; + } + else if ( pathToParcel.indexOf(USER) == 0 ) + { + placeHolder = "user"; + } + else if ( pathToParcel.indexOf("vnd.sun.star.tdoc:") == 0 ) + { + placeHolder = "document"; + } + // TODO handling document packages ??? not really sure of package url +/* else + { + } */ + return placeHolder; + } + + // TODO probably should be private should not be necessary + // to be exposed at all only used in lang providers at the moment + // to generate URL for script, editors should use a model of script + // source and not interact with the URL + // Also if it is to remain needs to be renamed to getParcelLocationURL + + // return URL string to parcel + public String getParcelLocation() + { + return parent.getPathToParcel(); + } + + + public String toString() + { + return "\nParcelLocation = " + getParcelLocation() + "\nLocationPlaceHolder = " + locationPlaceHolder + super.toString(); + } + + public URL[] getClassPath() throws java.net.MalformedURLException + { + try + { + String classpath = (String)getLanguageProperties().get("classpath"); + Vector paths = null; + + if ( classpath == null ) + { + classpath = ""; + } + + String parcelPath = getParcelLocation(); + // make sure path ends with / + if ( !parcelPath.endsWith("/") ) + { + parcelPath += "/"; + } + + // replace \ with / + parcelPath = parcelPath.replace( '\\', '/' ); + + Vector classPathVec = new Vector(); + StringTokenizer stk = new StringTokenizer(classpath, ":"); + while ( stk.hasMoreElements() ) + { + String relativeClasspath = (String)stk.nextElement(); + String pathToProcess = PathUtils.make_url( parcelPath, relativeClasspath); + URL url = createURL( pathToProcess ); + if ( url != null ) + { + classPathVec.add ( url ); + } + + } + if ( classPathVec.size() == 0) + { + URL url = createURL( parcelPath ); + if ( url != null ) + { + classPathVec.add(url); + } + } + + return (URL[])classPathVec.toArray( new URL[0]); + } + catch ( Exception e ) + { + LogUtils.DEBUG("Failed to build class path " + e.toString() ); + LogUtils.DEBUG( LogUtils.getTrace( e ) ); + return new URL[0]; + } + + } + private URL createURL( String path ) throws java.net.MalformedURLException + { + URL url = null; + int indexOfColon = path.indexOf(":"); + String scheme = path.substring( 0, indexOfColon ); + UCBStreamHandler handler = new UCBStreamHandler( parent.parent.m_xCtx, scheme, parent.m_xSFA); + + path += UCBStreamHandler.separator; + url = new URL(null, path, handler); + return url; + } + + // TODO should decide whether this should throw or not + // decide whether it should be public or protected ( final ? ) + public void loadSource() + { + try + { + URL sourceUrl = getSourceURL(); + LogUtils.DEBUG("** In load source BUT not loading yet for " + sourceUrl ); + + if ( sourceUrl != null ) + { + StringBuffer buf = new StringBuffer(); + InputStream in = sourceUrl.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 (java.io.IOException ignore ) { + LogUtils.DEBUG("** Failed to read scriot from url " + ignore.toString() ); + } + + source = buf.toString(); + hasSource = true; + } + } + catch (java.io.IOException e) { + LogUtils.DEBUG("** Failed to read scriot from url " + e.toString()); + } + + } + protected boolean writeSourceFile() + { + String parcelLocation = parent.getPathToParcel(); + String sourceFilePath = parent.getPathToParcel() + "/" + getLanguageName(); + boolean result = false; + OutputStream os = null; + try + { + XSimpleFileAccess2 xSFA2 = ( XSimpleFileAccess2 ) + UnoRuntime.queryInterface( XSimpleFileAccess2.class, + parent.m_xSFA ); + if ( xSFA2 != null ) + { + ByteArrayInputStream bis = new ByteArrayInputStream( getSourceBytes() ); + XInputStreamImpl xis = new XInputStreamImpl( bis ); + xSFA2.writeFile( sourceFilePath, xis ); + xis.closeInput(); + result = true; + } + } + // TODO re-examine exception processing should probably throw + // exceptions back to caller + catch ( Exception ignore ) + + { + } + return result; + } + protected boolean removeSourceFile() + { + String parcelLocation = parent.getPathToParcel(); + String sourceFilePath = parcelLocation + "/" + getLanguageName(); + boolean result = false; + try + { + parent.m_xSFA.kill( sourceFilePath ); + result = true; + } + // TODO reexamine exception handling + catch ( Exception e ) + { + } + return result; + } + + public URL getSourceURL() throws java.net.MalformedURLException + { + String sUrl = null; + URL scriptURL = null; + + sUrl = getParcelLocation(); + sUrl = PathUtils.make_url( sUrl, getLanguageName() ); + LogUtils.DEBUG("Creating script url for " + sUrl ); + scriptURL = createURL( sUrl ); + return scriptURL; + } +} diff --git a/scripting/java/com/sun/star/script/framework/container/UnoPkgContainer.java b/scripting/java/com/sun/star/script/framework/container/UnoPkgContainer.java new file mode 100644 index 000000000000..edf6a2d806b7 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/container/UnoPkgContainer.java @@ -0,0 +1,438 @@ +/************************************************************************* + * + * 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.container; + +import com.sun.star.script.framework.log.LogUtils; +import com.sun.star.script.framework.provider.PathUtils; +import com.sun.star.script.framework.io.XOutputStreamWrapper; +import com.sun.star.script.framework.io.XInputStreamWrapper; + +import java.util.Map; +import java.util.HashMap; +import java.io.OutputStream; +import java.io.InputStream; + +import com.sun.star.uno.XComponentContext; + +import com.sun.star.uno.UnoRuntime; + +import com.sun.star.io.XOutputStream; +import com.sun.star.io.XTruncate; + +import com.sun.star.deployment.XPackage; +import com.sun.star.deployment.ExtensionRemovedException; + +public class UnoPkgContainer extends ParcelContainer +{ + + private Map registeredPackages = new HashMap(); + protected String extensionDb; + protected String extensionRepository; + + public UnoPkgContainer( XComponentContext xCtx, String locationURL, + String _extensionDb, String _extensionRepository, String language ) throws com.sun.star.lang.IllegalArgumentException, com.sun.star.lang.WrappedTargetException + { + super( xCtx, locationURL, language, false ); + extensionDb = _extensionDb; + extensionRepository = _extensionRepository; + init(); + } + + // gets the ParcelContainer for persisted uno packages + public ParcelContainer getRegisteredUnoPkgContainer( String url ) + { + if (!url.endsWith("/")) + { + url += "/"; + } + + LogUtils.DEBUG("** getRegisterPackage ctx = " + containerUrl ); + LogUtils.DEBUG("** getRegisterPackage for uri " + url ); + LogUtils.DEBUG("** getRegisterPackage for langugage " + language ); + ParcelContainer result = (ParcelContainer)registeredPackages.get( url ); + LogUtils.DEBUG("getRegisterPackage result is " + result ); + return result; + } + + public boolean hasRegisteredUnoPkgContainer( String url ) + { + boolean result = false; + if ( getRegisteredUnoPkgContainer( url ) != null ) + { + result = true; + } + return result; + } + + private void registerPackageContainer( String url, ParcelContainer c ) + { + if (!url.endsWith("/")) + { + url += "/"; + } + + LogUtils.DEBUG("RegisterPackage ctx = " + containerUrl ); + LogUtils.DEBUG("RegisterPackage language = " + language ); + LogUtils.DEBUG("RegisterPackage " + c + " for url " + url ); + registeredPackages.put( url, c ); + } + + public void deRegisterPackageContainer( String url ) + { + if (!url.endsWith("/")) + { + url += "/"; + } + + LogUtils.DEBUG("In deRegisterPackageContainer for " + url ); + if ( hasRegisteredUnoPkgContainer( url ) ) + { + try + { + DeployedUnoPackagesDB db = getUnoPackagesDB(); + if ( db != null ) + { + if ( db.removePackage( language, url ) ) + { + writeUnoPackageDB( db ); + ParcelContainer container = + ( ParcelContainer ) registeredPackages.get( url ); + if ( !container.hasElements() ) + { + // When all libraries within a package bundle + // ( for this language ) are removed also + // remove the container from its parent + // Otherwise, a container ( with no containees ) + // representing the uno package bundle will + // still exist and so will get displayed + if ( container.parent() != null ) + { + container.parent().removeChildContainer( container ); + } + } + registeredPackages.remove( url ); + } + } + } + catch (Exception e) + { + //TODO revisit exception handling and exception here + //means something very wrong + LogUtils.DEBUG("***** deRegisterPackageContainer() got exception " + e ); + } + } + LogUtils.DEBUG("Leaving deRegisterPackageContainer for " + url ); + } + + private void init() throws com.sun.star.lang.IllegalArgumentException, com.sun.star.lang.WrappedTargetException + { + LogUtils.DEBUG("getting container for " + containerUrl ); + DeployedUnoPackagesDB db = null; + try + { + db = getUnoPackagesDB(); + if ( db != null ) + { + String[] packages = db.getDeployedPackages( language ); + + for ( int i=0; i<packages.length;i++) + { + try + { + processUnoPackage( packages[i], language ); + } + catch ( com.sun.star.lang.IllegalArgumentException ila) + { + LogUtils.DEBUG("Failed to process " + packages[i] + " for " + language); + LogUtils.DEBUG(" Reason: " + ila ); + } + catch( Exception e ) + { + // TODO proper exception or do we wish + // to ignore errors here + LogUtils.DEBUG("Something very wrong!!!!!"); + LogUtils.DEBUG("Failed to process " + packages[i] + " for " + language); + LogUtils.DEBUG(" Reason: " + e ); + } + } + } + } + catch ( com.sun.star.lang.WrappedTargetException e ) + { + // no deployed packages + LogUtils.DEBUG("No deployed uno-packages for " + containerUrl ); + } + } + + + public ScriptMetaData findScript( ParsedScriptUri psu ) throws com.sun.star.container.NoSuchElementException, com.sun.star.lang.WrappedTargetException + + { + ScriptMetaData scriptData = null; + + String language = psu.language; + String functionName = psu.function; + String parcelName = psu.parcel; + String location = psu.location; + + LogUtils.DEBUG("*** UnoPkgContainer.findScript() ***" + + "\ncontainerUrl = " + containerUrl + + "\nfunction = " + functionName + + "\nlocation = " + location + + "\nparcel = " + parcelName ); + + ParcelContainer pc = getChildContainer( location ); + + if ( pc == null ) + { + throw new com.sun.star.lang.WrappedTargetException( "Failed to resolve script " , null, new com.sun.star.lang.IllegalArgumentException( "Cannot resolve script location for script = " + functionName ) ); + } + + scriptData = pc.findScript( psu ); + return scriptData; + + } + + private DeployedUnoPackagesDB getUnoPackagesDB() throws com.sun.star.lang.WrappedTargetException + { + InputStream is = null; + DeployedUnoPackagesDB dp = null; + try + { +// String path = containerUrl.substring( 0, containerUrl.lastIndexOf("/") ); + String packagesUrl = PathUtils.make_url( extensionDb, "/Scripts/" + extensionRepository + "-extension-desc.xml" ); + LogUtils.DEBUG("getUnoPackagesDB() looking for existing db in " + packagesUrl ); + if ( m_xSFA.exists( packagesUrl ) ) + { + if ( packagesUrl.startsWith( "vnd.sun.star.tdoc" ) ) + { + // handles using XStorage directly + throw new com.sun.star.lang.WrappedTargetException("Can't handle documents yet"); + } + + is = new XInputStreamWrapper( m_xSFA.openFileRead( packagesUrl ) ); + dp = new DeployedUnoPackagesDB( is ); + try + { + is.close(); + is = null; + } + catch ( Exception ignore ) + { + } + } + else + { + LogUtils.DEBUG("getUnoPackagesDB() " + packagesUrl + " does not exist"); + } + } + catch( Exception e ) + { + LogUtils.DEBUG("getUnoPackagesDB() caught Exception: " + e ); + LogUtils.DEBUG( LogUtils.getTrace( e ) ); + throw new com.sun.star.lang.WrappedTargetException( e.toString()); + } + finally + { + if ( is != null ) + { + try + { + is.close(); + is = null; + } + catch ( Exception ignore ) + { + } + } + } + + return dp; + } + + private void writeUnoPackageDB( DeployedUnoPackagesDB dp ) throws com.sun.star.lang.IllegalArgumentException, com.sun.star.lang.WrappedTargetException + { + LogUtils.DEBUG("In writeUnoPackageDB() "); + + XOutputStream xos = null; + OutputStream os = null; + try + { +// String path = containerUrl.substring( 0, containerUrl.lastIndexOf("/") ); + String packagesUrl = PathUtils.make_url( extensionDb, "/Scripts/" + extensionRepository + "-extension-desc.xml" ); + xos = m_xSFA.openFileWrite( packagesUrl ); + XTruncate xTrc = (XTruncate) UnoRuntime.queryInterface( XTruncate.class, xos ); + if ( xTrc != null ) + { + LogUtils.DEBUG("In writeUnoPackageDB() Truncating...." ); + xTrc.truncate(); + } + else + { + LogUtils.DEBUG("In writeUnoPackageDB() CANT Truncate...." ); + } + os = new XOutputStreamWrapper( xos ); + dp.write( os ); + try + { + os.close(); // will close xos + os = null; + } + catch( Exception ignore ) + { + } + } + catch( Exception e ) + { + LogUtils.DEBUG("In writeUnoPackageDB() Exception: " + e ); + throw new com.sun.star.lang.WrappedTargetException( e.toString()); + } + finally + { + if ( os != null ) + { + try + { + os.close(); // will close xos + os = null; + } + catch ( Exception ignore ) + { + } + } + } + } + + public void processUnoPackage( XPackage dPackage, String language ) throws com.sun.star.lang.IllegalArgumentException, com.sun.star.lang.WrappedTargetException, com.sun.star.container.ElementExistException + { + LogUtils.DEBUG("** in processUnoPackage " ); + String uri = null; + DeployedUnoPackagesDB db = null; + uri = dPackage.getURL(); + + if ( !uri.endsWith( "/" ) ) + { + uri += "/"; + } + + LogUtils.DEBUG("** processUnoPackage getURL() -> " + uri ); + LogUtils.DEBUG("** processUnoPackage getName() -> " + dPackage.getName() ); + LogUtils.DEBUG("** processUnoPackage getMediaType() -> " + dPackage.getPackageType().getMediaType() ); + try + { + LogUtils.DEBUG("** processUnoPackage getDisplayName() -> " + dPackage.getDisplayName() ); + } + catch (com.sun.star.deployment.ExtensionRemovedException e) + { + throw new com.sun.star.lang.WrappedTargetException(e.toString(), this, e); + } + + processUnoPackage( uri, language ); + + db = getUnoPackagesDB(); + if ( db == null ) + { + try + { + db = new DeployedUnoPackagesDB(); + } + catch ( java.io.IOException ioe ) + { + throw new com.sun.star.lang.WrappedTargetException( ioe.toString()); + } + } + db.addPackage( language, uri ); + writeUnoPackageDB( db ); + } + + private void processUnoPackage( String uri, String language ) throws com.sun.star.lang.IllegalArgumentException, com.sun.star.lang.WrappedTargetException, com.sun.star.container.ElementExistException + { + if ( hasRegisteredUnoPkgContainer( uri ) ) + { + throw new com.sun.star.container.ElementExistException( "Already a registered uno package " + uri + " for language " + language ); + } + LogUtils.DEBUG("processUnoPackage - URL = " + uri ); + LogUtils.DEBUG("processUnoPackage - script library package"); + String parentUrl = uri; + + if ( uri.indexOf( "%2Funo_packages%2F" ) > -1 || + uri.indexOf( "/uno_packages/" ) > -1 || + uri.indexOf("$UNO_USER_PACKAGES_CACHE/") > -1 || + uri.indexOf("$UNO_SHARED_PACKAGES_CACHE/") > -1 || + uri.indexOf("$BUNDLED_EXTENSIONS/") > -1 ) + { + //its in a bundle need to determine the uno-package file its in + LogUtils.DEBUG("processUnoPackage - is part of a uno bundle"); + + int index = uri.lastIndexOf("/"); + if ( uri.endsWith("/") ) + { + uri = uri.substring( 0, index ); + index = uri.lastIndexOf("/"); + } + + if ( index > -1 ) + { + parentUrl = uri.substring( 0, index ); + LogUtils.DEBUG("processUnoPackage - composition is contained in " + parentUrl); + } + + ParcelContainer pkgContainer = getChildContainerForURL( parentUrl ); + if ( pkgContainer == null ) + { + pkgContainer = new ParcelContainer( this, m_xCtx, parentUrl, language, false ); + if ( pkgContainer.loadParcel( uri ) == null ) + { + throw new com.sun.star.lang.IllegalArgumentException( "Couldn't load script library from composition package " + uri + " for language " + language ); + + } + addChildContainer( pkgContainer ); + } + else + { + if ( pkgContainer.loadParcel( uri ) == null ) + { + throw new com.sun.star.lang.IllegalArgumentException( "Couldn't load script library from composition package " + uri + " for language " + language ); + } + + } + registerPackageContainer( uri, pkgContainer ); + } + else + { + // stand-alone library package, e.g. not contained in + // an uno package + if ( loadParcel( uri ) == null ) + { + throw new com.sun.star.lang.IllegalArgumentException( "Couldn't load script library package " + uri + " for language " + language ); + } + registerPackageContainer( uri, this ); + } + + } + +} diff --git a/scripting/java/com/sun/star/script/framework/container/XMLParser.java b/scripting/java/com/sun/star/script/framework/container/XMLParser.java new file mode 100644 index 000000000000..5e5bd00fac0e --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/container/XMLParser.java @@ -0,0 +1,38 @@ +/************************************************************************* + * + * 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.container; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import org.w3c.dom.Document; + +public interface XMLParser { + public Document parse(InputStream inputStream) throws IOException; + public void write(Document doc, OutputStream out) throws IOException; +} diff --git a/scripting/java/com/sun/star/script/framework/container/XMLParserFactory.java b/scripting/java/com/sun/star/script/framework/container/XMLParserFactory.java new file mode 100644 index 000000000000..52405fe0ea7c --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/container/XMLParserFactory.java @@ -0,0 +1,180 @@ +/************************************************************************* + * + * 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.container; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.lang.reflect.Method; + +import javax.xml.parsers.*; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +public class XMLParserFactory { + + private static XMLParser parser = null; + private static String officedtdurl = null; + + private XMLParserFactory() {} + + public static XMLParser getParser() { + if (parser == null) { + synchronized (XMLParserFactory.class) { + if (parser == null) + parser = new DefaultParser(); + } + } + return parser; + } + + public static void setParser(XMLParser p) { + parser = p; + } + + public static void setOfficeDTDURL(String url) { + officedtdurl = url; + } + + private static class DefaultParser implements XMLParser { + + private DocumentBuilderFactory factory; + + public DefaultParser() { + factory = DocumentBuilderFactory.newInstance(); + } + + public Document parse(InputStream inputStream) throws IOException { + Document result = null; + InputSource is = null; + + try { + DocumentBuilder builder = factory.newDocumentBuilder(); + + is = new InputSource(inputStream); + + if (officedtdurl != null) { + is.setSystemId(officedtdurl); + } + + result = builder.parse(is); + } + catch (SAXParseException spe) { + throw new IOException(spe.getMessage()); + } + catch (SAXException se) { + throw new IOException(se.getMessage()); + } + catch (ParserConfigurationException pce) { + throw new IOException(pce.getMessage()); + } + return result; + } + + public void write(Document doc, OutputStream out) throws IOException { + Class clazz = doc.getClass(); + String name = clazz.getName(); + + // depending on the class of the Document object use introspection + // to invoke the appropriate methods for writing the XML + // this code is based on the code used by the NetBeans + // class XMLUtilImpl in the openide module + try { + if (name.equals("com.sun.xml.tree.XmlDocument") || + name.equals("org.apache.crimson.tree.XmlDocument")) { + + // these DOM implementations are self writing + Method write; + write = clazz.getDeclaredMethod("write", + new Class[] {OutputStream.class}); + write.invoke(doc, new Object[] {out}); + } + else { + // try xerces serialize package using introspection + ClassLoader cl = this.getClass().getClassLoader(); + + Class serializerClass = null; + Class formatterClass = null; + + try { + serializerClass = Class.forName( + "org.apache.xml.serialize.XMLSerializer", true, cl); + formatterClass = Class.forName( + "org.apache.xml.serialize.OutputFormat", true, cl); + } catch (ClassNotFoundException cnfe) { + String prefix = "com.sun.org.apache.xml.internal."; + + serializerClass = Class.forName( + prefix + "serialize.XMLSerializer" , true, cl); + formatterClass = Class.forName( + prefix + "serialize.OutputFormat", true, cl); + } + + Object serializerObject = serializerClass.newInstance(); + Object formatterObject = formatterClass.newInstance(); + + // improve output readability using the OutputFormat class + Method method = null; + method = formatterClass.getMethod("setMethod", + new Class[] {String.class}); + method.invoke(formatterObject, new Object[] {"xml"}); + method = formatterClass.getMethod("setIndenting", + new Class[] {Boolean.TYPE}); + method.invoke(formatterObject, new Object[] {Boolean.TRUE}); + + // now set up an instance of XMLSerializer with our + // OutputStream and serialize our Document + method = serializerClass.getMethod("setOutputByteStream", + new Class[] {OutputStream.class}); + method.invoke(serializerObject, new Object[] {out}); + method = serializerClass.getMethod("setOutputFormat", + new Class[] {formatterClass}); + method.invoke(serializerObject, + new Object[] {formatterObject}); + + method = serializerClass.getMethod("asDOMSerializer", + new Class[0]); + Object impl = method.invoke(serializerObject, + new Object[0]); + + method = impl.getClass().getMethod("serialize", + new Class[] {Document.class}); + method.invoke(impl, new Object[] {doc}); + } + } catch (NoSuchMethodException ex) { + throw new IOException(ex.getMessage()); + } catch (ClassNotFoundException ex) { + throw new IOException(ex.getMessage()); + } catch (Exception ex) { + throw new IOException(ex.getMessage()); + } + } + } +} diff --git a/scripting/java/com/sun/star/script/framework/io/UCBStreamHandler.java b/scripting/java/com/sun/star/script/framework/io/UCBStreamHandler.java new file mode 100644 index 000000000000..6ca6fabff260 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/io/UCBStreamHandler.java @@ -0,0 +1,281 @@ +/************************************************************************* +* + * 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.io; + +import java.net.*; +import java.io.*; +import java.util.*; +import java.util.zip.*; + +import com.sun.star.uno.XComponentContext; +import com.sun.star.ucb.XSimpleFileAccess; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.io.XInputStream; +import com.sun.star.io.XOutputStream; +import com.sun.star.io.XTruncate; + +import com.sun.star.script.framework.log.LogUtils; +import com.sun.star.script.framework.provider.PathUtils; + +public class UCBStreamHandler extends URLStreamHandler { + + public final static String separator = "/ucb/"; + + private XComponentContext m_xContext = null; + private XMultiComponentFactory m_xMultiComponentFactory = null; + private XSimpleFileAccess m_xSimpleFileAccess = null; + private HashMap m_jarStreamMap = new HashMap(12); + public static String m_ucbscheme; + + public UCBStreamHandler( XComponentContext ctxt, String scheme, XSimpleFileAccess xSFA ) + { + LogUtils.DEBUG( "UCBStreamHandler ctor, scheme = " + scheme ); + this.m_xContext = ctxt; + this.m_ucbscheme = scheme; + this.m_xSimpleFileAccess = xSFA; + } + + public void parseURL(URL url, String spec, int start, int limit) { + LogUtils.DEBUG("**XUCBStreamHandler, parseURL: " + url + " spec: " + spec + " start: " + start + " limit: " + limit ); + + String file = url.getFile(); + if (file == null) + file = spec.substring(start, limit); + else + file += spec.substring(start, limit); + + LogUtils.DEBUG("**For scheme = " + m_ucbscheme ); + LogUtils.DEBUG("**Setting path = " + file ); + setURL(url, m_ucbscheme, null, -1, null, null, file, null, null); + } + + public URLConnection openConnection(URL u) throws IOException { + return new UCBConnection(u); + } + + private class UCBConnection extends URLConnection { + + public UCBConnection(URL url) { + super(url); + } + + public void connect() { + } + + public InputStream getInputStream() throws IOException { + LogUtils.DEBUG("UCBConnectionHandler GetInputStream on " + url ); + String sUrl = url.toString(); + if (sUrl.lastIndexOf(separator) == -1) { + LogUtils.DEBUG("getInputStream straight file load" ); + return getFileStreamFromUCB(sUrl); + } + else { + String path = sUrl.substring(0, sUrl.lastIndexOf(separator) ); + String file = sUrl.substring( + sUrl.lastIndexOf(separator) + separator.length()); + LogUtils.DEBUG("getInputStream, load of file from another file eg. " + file + " from " + path ); + return getUCBStream(file, path); + } + } + public OutputStream getOutputStream() throws IOException { + LogUtils.DEBUG("UCBConnectionHandler getOutputStream on " + url ); + OutputStream os = null; + try + { + String sUrl = url.toString(); + if ( !( sUrl.lastIndexOf(separator) == -1) ) { + String path = sUrl.substring(0, sUrl.lastIndexOf(separator)); + String file = sUrl.substring( + sUrl.lastIndexOf(separator) + separator.length()); + + if ( m_xSimpleFileAccess.isReadOnly( path ) ) + { + throw new java.io.IOException("File is read only"); + } + + LogUtils.DEBUG("getOutputStream, create o/p stream for file eg. " + path ); + + // we will only deal with simple file write + XOutputStream xos = m_xSimpleFileAccess.openFileWrite( path ); + XTruncate xtrunc = ( XTruncate ) UnoRuntime.queryInterface( XTruncate.class, xos ); + if ( xtrunc != null ) + { + xtrunc.truncate(); + } + os = new XOutputStreamWrapper( xos ); + } + if ( os == null ) + { + throw new IOException("Failed to get OutputStream for " + sUrl ); + } + } + catch ( com.sun.star.ucb.CommandAbortedException cae ) + { + LogUtils.DEBUG("caught exception: " + cae.toString() + " getting writable stream from " + url ); + throw new IOException( cae.toString() ); + } + catch ( com.sun.star.uno.Exception e ) + { + LogUtils.DEBUG("caught unknown exception: " + e.toString() + " getting writable stream from " + url ); + throw new IOException( e.toString() ); + } + return os; + } + } + + + private InputStream getUCBStream(String file, String path) + throws IOException + { + InputStream is = null; + InputStream result = null; + + try { + if (path.endsWith(".jar")) { + is = (InputStream)m_jarStreamMap.get(path); + + if (is == null) { + is = getFileStreamFromUCB(path); + m_jarStreamMap.put(path, is); + } + else { + try { + is.reset(); + } + catch (IOException e) { + is.close(); + is = getFileStreamFromUCB(path); + m_jarStreamMap.put(path, is); + } + } + result = getFileStreamFromJarStream(file, is); + } + else + { + String fileUrl = PathUtils.make_url(path,file); + result = getFileStreamFromUCB(fileUrl); + } + } + finally { + if (is != null) { + try { + is.close(); + } + catch (IOException ioe) { + LogUtils.DEBUG("Caught exception closing stream: " + + ioe.getMessage()); + } + } + } + return result; + } + + private InputStream getFileStreamFromJarStream(String file, InputStream is) + throws IOException + { + ZipInputStream zis = null; + ZipEntry entry = null; + boolean found = false; + + zis = new ZipInputStream(is); + + while (zis.available() != 0) { + entry = (ZipEntry)zis.getNextEntry(); + + if (entry.getName().equals(file)) { + return zis; + } + } + return null; + } + + private InputStream getFileStreamFromUCB(String path) + throws IOException + { + InputStream result = null; + XInputStream xInputStream = null; + + try { + LogUtils.DEBUG("Trying to read from " + path ); + xInputStream = m_xSimpleFileAccess.openFileRead(path); + LogUtils.DEBUG("sfa appeared to read file " ); + byte[][] inputBytes = new byte[1][]; + + int ln = 0; + int sz = m_xSimpleFileAccess.getSize(path); + // TODO don't depend on result of available() or size() + // just read stream 'till complete + if ( sz == 0 ) + { + if ( xInputStream.available() > 0 ) + { + sz = xInputStream.available(); + } + } + LogUtils.DEBUG("size of file " + path + " is " + sz ); + LogUtils.DEBUG("available = " + xInputStream.available() ); + inputBytes[0] = new byte[sz]; + + ln = xInputStream.readBytes(inputBytes, sz); + + if (ln != sz) { + throw new IOException( + "Failed to read " + sz + " bytes from XInputStream"); + } + + result = new ByteArrayInputStream(inputBytes[0]); + } + catch (com.sun.star.io.IOException ioe) { + LogUtils.DEBUG("caught exception " + ioe ); + throw new IOException(ioe.getMessage()); + } + catch (com.sun.star.uno.Exception e) { + LogUtils.DEBUG("caught exception " + e ); + throw new IOException(e.getMessage()); + } + finally + { + if (xInputStream != null) { + try { + xInputStream.closeInput(); + } + catch (Exception e2) { + LogUtils.DEBUG( + "Error closing XInputStream:" + e2.getMessage()); + } + } + } + return result; + } + + private String convertClassNameToFileName(String name) { + return name.replace('.', File.separatorChar) + ".class"; + } + +} diff --git a/scripting/java/com/sun/star/script/framework/io/XInputStreamImpl.java b/scripting/java/com/sun/star/script/framework/io/XInputStreamImpl.java new file mode 100644 index 000000000000..c83c030662a4 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/io/XInputStreamImpl.java @@ -0,0 +1,119 @@ +/************************************************************************* + * + * 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.io; + +import com.sun.star.io.XInputStream; +import java.io.InputStream; +import java.io.IOException; + +public class XInputStreamImpl implements XInputStream +{ + InputStream is; + public XInputStreamImpl( InputStream is ) + { + this.is = is; + } + + public int readBytes( /*OUT*/byte[][] aData, /*IN*/int nBytesToRead ) throws com.sun.star.io.NotConnectedException, com.sun.star.io.BufferSizeExceededException, com.sun.star.io.IOException + { + aData[ 0 ] = new byte[ nBytesToRead ]; + + int totalBytesRead = 0; + + try + { + int bytesRead = 0; + while ( ( bytesRead = is.read( aData[ 0 ], totalBytesRead, nBytesToRead ) ) > 0 && ( totalBytesRead < nBytesToRead ) ) + { + totalBytesRead += bytesRead; + nBytesToRead -= bytesRead; + } + } + catch ( IOException e ) + { + throw new com.sun.star.io.IOException( e.toString() ); + } + catch ( IndexOutOfBoundsException aie ) + { + throw new com.sun.star.io.BufferSizeExceededException( aie.toString() ); + } + return totalBytesRead; + } + + public int readSomeBytes( /*OUT*/byte[][] aData, /*IN*/int nMaxBytesToRead ) throws com.sun.star.io.NotConnectedException, com.sun.star.io.BufferSizeExceededException, com.sun.star.io.IOException + { + int bytesToRead = nMaxBytesToRead; + int availableBytes = available(); + if ( availableBytes < nMaxBytesToRead ) + { + bytesToRead = availableBytes; + } + int read = readBytes( aData, bytesToRead ); + return read; + } + + public void skipBytes( /*IN*/int nBytesToSkip ) throws com.sun.star.io.NotConnectedException, com.sun.star.io.BufferSizeExceededException, com.sun.star.io.IOException + { + long bytesSkipped = 0; + try + { + bytesSkipped = is.skip( (long)nBytesToSkip ); + } + catch ( IOException e ) + { + throw new com.sun.star.io.IOException( e.toString() ); + } + } + + public int available( ) throws com.sun.star.io.NotConnectedException, com.sun.star.io.IOException + { + int bytesAvail = 0; + try + { + bytesAvail = is.available(); + } + catch ( IOException e ) + { + throw new com.sun.star.io.IOException( e.toString() ); + } + return bytesAvail; + } + + public void closeInput( ) throws com.sun.star.io.NotConnectedException, com.sun.star.io.IOException + { + try + { + is.close(); + } + catch( IOException e ) + { + throw new com.sun.star.io.IOException( e.toString() ); + } + } + +} diff --git a/scripting/java/com/sun/star/script/framework/io/XInputStreamWrapper.java b/scripting/java/com/sun/star/script/framework/io/XInputStreamWrapper.java new file mode 100644 index 000000000000..cfc1b8489739 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/io/XInputStreamWrapper.java @@ -0,0 +1,102 @@ +/************************************************************************* + * + * 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.io; + +import java.io.InputStream; +import com.sun.star.io.XInputStream; + +public class XInputStreamWrapper extends InputStream { + private XInputStream m_xInputStream; + + public XInputStreamWrapper(XInputStream xInputStream) { + m_xInputStream = xInputStream; + } + + public int read() throws java.io.IOException + { + byte[][] byteRet = new byte[1][0]; + long numRead; + + try { + numRead = m_xInputStream.readBytes(byteRet, 1); + } + catch (com.sun.star.io.IOException ioe) { + throw new java.io.IOException(ioe.getMessage()); + } + + if (numRead != 1) { + return -1; + } + return byteRet[0][0]; + } + + public int read( byte[] b ) throws java.io.IOException + { + byte[][] byteRet = new byte[1][]; + byteRet[0] = b; + try + { + return m_xInputStream.readBytes( byteRet, b.length ); + } + catch ( com.sun.star.io.IOException ioe) + { + throw new java.io.IOException(ioe.getMessage()); + } + } + + public long skip(long n) throws java.io.IOException + { + try { + m_xInputStream.skipBytes((int)n); + return n; + } + catch (com.sun.star.io.IOException ioe) { + throw new java.io.IOException(ioe.getMessage()); + } + } + + public int available() throws java.io.IOException + { + try { + return m_xInputStream.available(); + } + catch (com.sun.star.io.IOException ioe) { + throw new java.io.IOException(ioe.getMessage()); + } + } + + public void close() throws java.io.IOException + { + try { + m_xInputStream.closeInput(); + } + catch (com.sun.star.io.IOException ioe) { + throw new java.io.IOException(ioe.getMessage()); + } + } + +} diff --git a/scripting/java/com/sun/star/script/framework/io/XOutputStreamWrapper.java b/scripting/java/com/sun/star/script/framework/io/XOutputStreamWrapper.java new file mode 100644 index 000000000000..dc2c7233708d --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/io/XOutputStreamWrapper.java @@ -0,0 +1,128 @@ +/************************************************************************* + * + * 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.io; +import java.io.*; +import com.sun.star.io.XOutputStream; + + +public class XOutputStreamWrapper extends OutputStream { + XOutputStream m_xOutputStream; + public XOutputStreamWrapper(XOutputStream xOs ) { + this.m_xOutputStream = xOs; + } + public void write(int b) + throws java.io.IOException + { + if ( m_xOutputStream == null ) + { + throw new java.io.IOException("Stream is null"); + } + byte[] bytes = new byte[1]; + bytes[0] = (byte) b; + try + { + m_xOutputStream.writeBytes( bytes ); + } + catch ( com.sun.star.io.IOException ioe ) + { + throw new java.io.IOException(ioe.getMessage()); + } + } + public void write(byte[] b) + throws java.io.IOException + { + + if ( m_xOutputStream == null ) + { + throw new java.io.IOException( "Stream is null" ); + } + try + { + m_xOutputStream.writeBytes( b ); + } + catch ( com.sun.star.io.IOException ioe ) + { + throw new java.io.IOException(ioe.getMessage()); + } + } + public void write( byte[] b, int off, int len ) + throws java.io.IOException + { + if ( m_xOutputStream == null ) + { + throw new java.io.IOException( "Stream is null" ); + } + byte[] bytes = new byte[len]; + for ( int i=off; i< off+len; i++ ) + { + bytes[i] = b[i]; + } + try + { + m_xOutputStream.writeBytes(bytes); + } + catch ( com.sun.star.io.IOException ioe ) + { + throw new java.io.IOException(ioe.getMessage()); + } + } + + public void flush() + throws java.io.IOException + { + if ( m_xOutputStream == null ) + { + throw new java.io.IOException( "Stream is null" ); + } + try + { + m_xOutputStream.flush(); + } + catch ( com.sun.star.io.IOException ioe ) + { + throw new java.io.IOException(ioe.getMessage()); + } + } + public void close() + throws java.io.IOException + { + if ( m_xOutputStream == null ) + { + throw new java.io.IOException( "Stream is null" ); + } + try + { + m_xOutputStream.closeOutput(); + } + catch ( com.sun.star.io.IOException ioe ) + { + throw new java.io.IOException(ioe.getMessage()); + } + } + + } + diff --git a/scripting/java/com/sun/star/script/framework/io/XStorageHelper.java b/scripting/java/com/sun/star/script/framework/io/XStorageHelper.java new file mode 100644 index 000000000000..7043438bc87e --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/io/XStorageHelper.java @@ -0,0 +1,278 @@ +/************************************************************************* + * + * 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.io; + +import com.sun.star.frame.XModel; + +import com.sun.star.container.XNameAccess; + +import com.sun.star.uno.XInterface; +import com.sun.star.uno.UnoRuntime; + +import com.sun.star.lang.XComponent; + +import com.sun.star.uno.AnyConverter; + +import com.sun.star.io.XStream; +import com.sun.star.io.XInputStream; +import com.sun.star.io.XOutputStream; + +import com.sun.star.embed.XStorage; +import com.sun.star.embed.XTransactedObject; + +import com.sun.star.document.XDocumentSubStorageSupplier; + +import com.sun.star.beans.XPropertySet; + +import com.sun.star.lang.XEventListener; +import com.sun.star.lang.EventObject; + +import com.sun.star.script.framework.log.LogUtils; +import com.sun.star.script.framework.provider.PathUtils; + +import java.util.*; +import java.io.*; + + +public class XStorageHelper implements XEventListener +{ + XStorage[] xStorages; + XStream xStream; + XInputStream xIs = null; + XOutputStream xOs = null; + static Map modelMap = new HashMap(); + XModel xModel = null; + private static XStorageHelper listener = new XStorageHelper(); + + private XStorageHelper() {} + public XStorageHelper( String path, int mode, boolean create ) throws IOException + { + String modelUrl = null; + int indexOfScriptsDir = path.lastIndexOf( "Scripts" ); + if ( indexOfScriptsDir > -1 ) + { + modelUrl = path.substring( 0, indexOfScriptsDir - 1 ); + path = path.substring( indexOfScriptsDir, path.length()); + } + + LogUtils.DEBUG("XStorageHelper ctor, path: " + path); + this.xModel = getModelForURL( modelUrl ); + + try + { + StringTokenizer tokens = new StringTokenizer(path, "/"); + + if (tokens.countTokens() == 0) + { + throw new IOException("Invalid path"); + } + XDocumentSubStorageSupplier xDocumentSubStorageSupplier = + (XDocumentSubStorageSupplier) UnoRuntime.queryInterface( + XDocumentSubStorageSupplier.class, xModel); + xStorages = new XStorage[tokens.countTokens() ]; + LogUtils.DEBUG("XStorageHelper ctor, path chunks length: " + xStorages.length ); + + for ( int i = 0; i < xStorages.length; i++ ) + { + LogUtils.DEBUG("XStorageHelper, processing index " + i ); + String name = tokens.nextToken(); + LogUtils.DEBUG("XStorageHelper, getting: " + name); + XStorage storage = null; + if ( i == 0 ) + { + storage = xDocumentSubStorageSupplier.getDocumentSubStorage( name, mode ); + if ( storage == null ) + { + LogUtils.DEBUG("** boo hoo Storage is null " ); + } + XPropertySet xProps = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class,storage ); + if ( xProps != null ) + { + String mediaType = AnyConverter.toString( xProps.getPropertyValue( "MediaType" ) ); + LogUtils.DEBUG("***** media type is " + mediaType ); + if ( !mediaType.equals("scripts") ) + { + xProps.setPropertyValue("MediaType","scripts"); + } + } + } + else + { + XNameAccess xNameAccess = (XNameAccess) + UnoRuntime.queryInterface(XNameAccess.class, xStorages[i-1]); + if (xNameAccess == null ) + { + disposeObject(); + throw new IOException("No name access " + name); + } + else if ( !xNameAccess.hasByName(name) || !xStorages[i-1].isStorageElement(name) ) + { + if ( !create ) + { + disposeObject(); + throw new IOException("No subdir: " + name); + } + else + { + // attempt to create new storage + LogUtils.DEBUG("Attempt to create new storage for " + name ); + } + } + + storage = xStorages[i-1].openStorageElement( + name, mode ); + } + if ( storage == null ) + { + disposeObject(); + throw new IOException("storage not found: " + name); + } + xStorages[ i ] = storage; + + } + } + catch ( com.sun.star.io.IOException ioe) + { + disposeObject(); + } + catch (com.sun.star.uno.Exception e) + { + disposeObject(); + throw new IOException(e.getMessage()); + } + } + + public synchronized static void addNewModel( XModel model ) + { + // TODO needs to cater for model for untitled document + modelMap.put( PathUtils.getOidForModel( model ), model ); + XComponent xComp = (XComponent) + UnoRuntime.queryInterface(XComponent.class, model); + + if ( xComp != null ) + { + try + { + xComp.addEventListener( listener ); + } + catch ( Exception e ) + { + // What TODO here ? + LogUtils.DEBUG( LogUtils.getTrace( e ) ); + } + } + } + + public void disposing( EventObject Source ) + { + XModel model = (XModel) + UnoRuntime.queryInterface(XModel.class,Source.Source ); + + if ( model != null ) + { + LogUtils.DEBUG(" Disposing doc " + model.getURL() ); + Object result = modelMap.remove( model ); + result = null; + } + } + public XStorage getStorage() + { + return xStorages[ xStorages.length - 1 ]; + } + public XModel getModel() + { + return xModel; + } + public void disposeObject() + { + disposeObject( false ); + } + public void disposeObject( boolean shouldCommit ) + { + LogUtils.DEBUG("In disposeObject"); + + for ( int i = xStorages.length -1 ; i > -1; i-- ) + { + LogUtils.DEBUG("In disposeObject disposing storage " + i ); + try + { + XStorage xStorage = xStorages[i]; + if ( shouldCommit ) + { + commit(xStorage); + } + disposeObject(xStorage); + LogUtils.DEBUG("In disposeObject disposed storage " + i ); + } + catch( Exception ignore ) + { + LogUtils.DEBUG("Exception disposing storage " + i ); + } + + } + + } + static public void disposeObject( XInterface xInterface ) + { + if (xInterface == null) { + return; + } + + XComponent xComponent = (XComponent) + UnoRuntime.queryInterface(XComponent.class, xInterface); + + if (xComponent == null) { + return; + } + xComponent.dispose(); + } + static public void commit( XInterface xInterface ) + { + XTransactedObject xTrans = (XTransactedObject) + UnoRuntime.queryInterface(XTransactedObject.class, xInterface); + if ( xTrans != null ) + { + try + { + xTrans.commit(); + } + catch ( Exception e ) + { + LogUtils.DEBUG("Something went bellyup exception: " + e ); + } + } + } + + public XModel getModelForURL( String url ) + { + //TODO does not cater for untitled documents + return (XModel)modelMap.get( url ); + } + +} + diff --git a/scripting/java/com/sun/star/script/framework/log/LogUtils.java b/scripting/java/com/sun/star/script/framework/log/LogUtils.java new file mode 100644 index 000000000000..ef4b1f9a56ec --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/log/LogUtils.java @@ -0,0 +1,68 @@ +package com.sun.star.script.framework.log; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +public class LogUtils { + + private static boolean m_bDebugEnabled = false; + + static + { + String debugFlag = + System.getProperties().getProperty("ScriptJavaRuntimeDebug"); + + if (debugFlag != null && debugFlag.length() > 0) + { + m_bDebugEnabled = debugFlag.equalsIgnoreCase("true"); + } + } + + // Ensure that instances of this class cannot be created + private LogUtils() { + } + + /** + * Print Debug Output + * + * @param msg message to be displayed + */ + public static void DEBUG(String msg) + { + if (m_bDebugEnabled) + { + System.out.println(msg); + } + } + + public static String getTrace( Exception e ) + { + ByteArrayOutputStream baos = null; + PrintStream ps = null; + String result = ""; + try + { + baos = new ByteArrayOutputStream( ); + ps = new PrintStream( baos ); + e.printStackTrace( ps ); + } + finally + { + try + { + if ( baos != null ) + { + baos.close(); + } + if ( ps != null ) + { + ps.close(); + } + } + catch ( Exception excp ) + { + } + } + return result; + } +} diff --git a/scripting/java/com/sun/star/script/framework/provider/ClassLoaderFactory.java b/scripting/java/com/sun/star/script/framework/provider/ClassLoaderFactory.java new file mode 100755 index 000000000000..641ca589d9a5 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/provider/ClassLoaderFactory.java @@ -0,0 +1,74 @@ +/************************************************************************* +* + * 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; + +import java.net.*; + +import com.sun.star.script.framework.log.LogUtils; +import com.sun.star.script.framework.container.ScriptMetaData; + +/** + * Class Loader Factory + * + * @author Noel Power + * @created August 2, 2002 + */ +public class ClassLoaderFactory +{ + private ClassLoaderFactory() {} + + public static ClassLoader getURLClassLoader( ScriptMetaData scriptData ) + throws NoSuitableClassLoaderException, MalformedURLException + { + ClassLoader parent = scriptData.getClass().getClassLoader(); + URL[] classPath = scriptData.getClassPath(); + LogUtils.DEBUG("Classpath has length " + classPath.length ); + for ( int i=0; i < classPath.length; i++ ) + { + LogUtils.DEBUG("ClassPath " + i + "} is " + classPath[ i ].toString() ); + } + return getURLClassLoader( parent, classPath ); + } + public static ClassLoader getURLClassLoader( ClassLoader parent, URL[] classpath) + throws NoSuitableClassLoaderException + { + ClassLoader loader = + new URLClassLoader( classpath, parent); + + if (loader != null) + { + return loader; + } + else + { + throw new NoSuitableClassLoaderException( + "Unable to create URLClassLoader"); + } + } + +} diff --git a/scripting/java/com/sun/star/script/framework/provider/EditorScriptContext.java b/scripting/java/com/sun/star/script/framework/provider/EditorScriptContext.java new file mode 100644 index 000000000000..a311669fdb38 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/provider/EditorScriptContext.java @@ -0,0 +1,100 @@ +/************************************************************************* +* + * 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; + +import com.sun.star.frame.XModel; +import com.sun.star.frame.XDesktop; +import com.sun.star.uno.XComponentContext; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.document.XScriptInvocationContext; + +import com.sun.star.script.provider.XScriptContext; + + +/** + * Description of the Class + * + * @author Noel Power + * @created August 2, 2002 + */ +public class EditorScriptContext implements XScriptContext +{ + private XDesktop m_xDeskTop; + private XComponentContext m_xComponentContext; + private XDesktop m_xCtx; + public EditorScriptContext( XComponentContext xmComponentContext, + XDesktop xDesktop ) + { + this.m_xComponentContext = xmComponentContext; + this.m_xDeskTop = xDesktop; + } + + //---------------------------------------------------------------------- + /** + Obtain the document reference on which the script can operate + + @returns + XModel interface + */ + public XModel getDocument() + { + XModel xModel = ( XModel ) UnoRuntime.queryInterface( XModel.class, + m_xDeskTop.getCurrentComponent() ); + + return xModel; + } + + public XScriptInvocationContext getInvocationContext() + { + XScriptInvocationContext xContext = ( XScriptInvocationContext ) UnoRuntime.queryInterface( + XScriptInvocationContext.class, getDocument() ); + return xContext; + } + + /** + Obtain the desktop reference on which the script can operate + + @returns + XDesktop interface + */ + public XDesktop getDesktop() + { + return m_xDeskTop; + } + + /** + Obtain the component context which the script can use to create other uno components + + @returns + XComponentContext interface + */ + public XComponentContext getComponentContext() + { + return m_xComponentContext; + } + +} diff --git a/scripting/java/com/sun/star/script/framework/provider/NoSuitableClassLoaderException.java b/scripting/java/com/sun/star/script/framework/provider/NoSuitableClassLoaderException.java new file mode 100755 index 000000000000..9b8613cf97cd --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/provider/NoSuitableClassLoaderException.java @@ -0,0 +1,53 @@ +/************************************************************************* + * + * 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; + +public class NoSuitableClassLoaderException extends Exception +{ + /** + * Constructs an <code>NoSuitableClassLoaderException</code> with <code>null</code> + * as its error detail message. + */ + public NoSuitableClassLoaderException() + { + super(); + } + /** + * Constructs an <code>NoSuitBaleClassLoaderException</code> with the specified detail + * message. The error message string <code>s</code> can later be + * retrieved by the <code>{@link java.lang.Throwable#getMessage}</code> + * method of class <code>java.lang.Throwable</code>. + * + * @param s the detail message. + */ + public NoSuitableClassLoaderException(String s) + { + super(s); + } + +} diff --git a/scripting/java/com/sun/star/script/framework/provider/PathUtils.java b/scripting/java/com/sun/star/script/framework/provider/PathUtils.java new file mode 100644 index 000000000000..2084425979fc --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/provider/PathUtils.java @@ -0,0 +1,87 @@ +/************************************************************************* + * + * 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; + +import java.util.StringTokenizer; + +import java.lang.reflect.Method; + +import com.sun.star.frame.XModel; +import com.sun.star.uno.IQueryInterface; + +public class PathUtils { + + public static String FILE_URL_PREFIX; + public static String BOOTSTRAP_NAME; + private static boolean m_windows = false; + + static { + // detect if windows platform + if (System.getProperty("os.name").startsWith("Windows")) + m_windows = true; + + FILE_URL_PREFIX = m_windows ? "file:///" : "file://"; + BOOTSTRAP_NAME = m_windows ? "bootstrap.ini" : "bootstraprc"; + } + public static String getOidForModel( XModel xModel ) + { + String oid = new String(""); + if ( xModel != null ) + { + try + { + Method getOid = IQueryInterface.class.getMethod("getOid", (java.lang.Class[])null); + if ( getOid != null ) + { + oid = (String)getOid.invoke( xModel, new Object[0] ); + } + + } + catch ( Exception ignore ) + { + } + } + return oid; + } + static public String make_url( String baseUrl, String url ) + { + StringBuffer buff = new StringBuffer( baseUrl.length() + url.length() ); buff.append( baseUrl ); + StringTokenizer t = new StringTokenizer( url, "/"); + while ( t.hasMoreElements() ) + { + if ( buff.charAt( buff.length() - 1 ) != '/' ) + { + buff.append('/'); + } + buff.append( java.net.URLEncoder.encode( (String)t.nextElement() ) ); } + return buff.toString(); + } + + private PathUtils() { + } +} diff --git a/scripting/java/com/sun/star/script/framework/provider/ScriptContext.java b/scripting/java/com/sun/star/script/framework/provider/ScriptContext.java new file mode 100644 index 000000000000..544bebb6ea9f --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/provider/ScriptContext.java @@ -0,0 +1,165 @@ +/************************************************************************* +* + * 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; + +import com.sun.star.document.XScriptInvocationContext; +import com.sun.star.frame.XModel; +import com.sun.star.frame.XDesktop; +import com.sun.star.uno.XComponentContext; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.uno.UnoRuntime; +import com.sun.star.beans.PropertyAttribute; +import com.sun.star.lib.uno.helper.PropertySet; +import com.sun.star.uno.Type; + +import com.sun.star.script.provider.XScriptContext; + +import com.sun.star.script.framework.log.LogUtils; + + +/** + * Description of the Class + * + * @author Noel Power + * @created August 2, 2002 + */ +public class ScriptContext extends PropertySet implements XScriptContext +{ + /** + * Description of the Class + * + * @author John Rice + * @created 18/09/02 + */ + + public final static String HM_DOC_REF = "DocumentReference"; + public final static String HM_DESKTOP = "Desktop"; + public final static String HM_COMPONENT_CONTEXT = "ComponentContext"; + + private final static String DOC_REF = "SCRIPTING_DOC_REF"; + private final static String DOC_URI = "SCRIPTING_DOC_URI"; + + + public XModel m_xModel = null; + public XScriptInvocationContext m_xInvocationContext = null; + public String m_sDocURI = null; + public XDesktop m_xDeskTop = null; + public Integer m_iStorageID = null; + public XComponentContext m_xComponentContext = null; + + public ScriptContext( XComponentContext xmComponentContext, + XDesktop xDesktop, XModel xModel, XScriptInvocationContext xInvocContext) + { + this.m_xDeskTop = xDesktop; + this.m_xComponentContext = xmComponentContext; + this.m_xModel = xModel; + this.m_xInvocationContext = xInvocContext; + + if ( m_xModel != null ) + { + registerProperty( DOC_URI, new Type(String.class), + (short)(PropertyAttribute.MAYBEVOID | PropertyAttribute.TRANSIENT), "m_sDocURI"); + } + + registerProperty( HM_DOC_REF, new Type(XModel.class), + (short)(PropertyAttribute.MAYBEVOID | PropertyAttribute.TRANSIENT), "m_xModel"); + registerProperty( HM_DESKTOP, new Type(XDesktop.class), + (short)(PropertyAttribute.MAYBEVOID | PropertyAttribute.TRANSIENT), "m_xDeskTop"); + registerProperty( HM_COMPONENT_CONTEXT, new Type(XDesktop.class), + (short)(PropertyAttribute.MAYBEVOID | PropertyAttribute.TRANSIENT), "m_xComponentContext"); + } + + public static XScriptContext createContext( XModel xModel, XScriptInvocationContext xInvocContext, + XComponentContext xCtxt, XMultiComponentFactory xMCF) + { + XScriptContext sc = null; + + try { + + Object xInterface = null; + XDesktop xDesktop = null; + + xInterface = xMCF.createInstanceWithContext( + "com.sun.star.frame.Desktop", xCtxt); + xDesktop = (XDesktop) + UnoRuntime.queryInterface(XDesktop.class, xInterface); + if ( xModel != null ) + { + sc = new ScriptContext(xCtxt, xDesktop, xModel, xInvocContext); + } + else + { + sc = new EditorScriptContext(xCtxt, xDesktop ); + } + + } + catch ( Exception e ) { + LogUtils.DEBUG( LogUtils.getTrace( e ) ); + } + return sc; + } + + //---------------------------------------------------------------------- + /** + Obtain the document reference on which the script can operate + + @returns + XModel interface + */ + public XModel getDocument() + { + return m_xModel; + } + + public XScriptInvocationContext getInvocationContext() + { + return m_xInvocationContext; + } + + /** + Obtain the desktop reference on which the script can operate + + @returns + XDesktop interface + */ + public XDesktop getDesktop() + { + return m_xDeskTop; + } + + /** + Obtain the component context which the script can use to create other uno components + + @returns + XComponentContext interface + */ + public XComponentContext getComponentContext() + { + return m_xComponentContext; + } + +} diff --git a/scripting/java/com/sun/star/script/framework/provider/ScriptEditor.java b/scripting/java/com/sun/star/script/framework/provider/ScriptEditor.java new file mode 100644 index 000000000000..e6654d2bd83f --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/provider/ScriptEditor.java @@ -0,0 +1,13 @@ +package com.sun.star.script.framework.provider; + +import com.sun.star.script.provider.XScriptContext; +import com.sun.star.script.framework.container.ScriptMetaData; + +public interface ScriptEditor +{ + public Object execute() throws Exception; + public void indicateErrorLine( int lineNum ); + public void edit(XScriptContext context, ScriptMetaData entry); + public String getTemplate(); + public String getExtension(); +} diff --git a/scripting/java/com/sun/star/script/framework/provider/ScriptProvider.java b/scripting/java/com/sun/star/script/framework/provider/ScriptProvider.java new file mode 100755 index 000000000000..e83410f3f35c --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/provider/ScriptProvider.java @@ -0,0 +1,745 @@ +/************************************************************************* +* + * 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; + +import com.sun.star.container.XNameContainer; + +import com.sun.star.uno.Exception; +import com.sun.star.uno.XComponentContext; +import com.sun.star.lang.XMultiComponentFactory; +import com.sun.star.lang.XInitialization; +import com.sun.star.lang.XTypeProvider; +import com.sun.star.lang.XServiceInfo; +import com.sun.star.frame.XModel; + +import com.sun.star.util.XMacroExpander; + +import com.sun.star.uno.UnoRuntime; +import com.sun.star.uno.AnyConverter; +import com.sun.star.uno.Type; + +import com.sun.star.beans.XPropertySet; +import com.sun.star.beans.XVetoableChangeListener; +import com.sun.star.beans.XPropertyChangeListener; +import com.sun.star.beans.XPropertySetInfo; +import com.sun.star.beans.Property; + +import com.sun.star.beans.XIntrospectionAccess; +import com.sun.star.script.XInvocation; + +import com.sun.star.script.provider.XScriptContext; +import com.sun.star.script.provider.XScriptProvider; +import com.sun.star.script.provider.XScript; +import com.sun.star.script.provider.ScriptFrameworkErrorException; +import com.sun.star.script.provider.ScriptFrameworkErrorType; + +import com.sun.star.script.browse.XBrowseNode; +import com.sun.star.script.browse.BrowseNodeTypes; + +import com.sun.star.script.framework.log.LogUtils; + +import com.sun.star.script.framework.container.ScriptMetaData; +import com.sun.star.script.framework.container.XMLParserFactory; +import com.sun.star.script.framework.container.ParcelContainer; +import com.sun.star.script.framework.container.ParsedScriptUri; +import com.sun.star.script.framework.container.UnoPkgContainer; + +import com.sun.star.ucb.Command; +import com.sun.star.ucb.XContentProvider; +import com.sun.star.ucb.XContent; +import com.sun.star.ucb.XCommandProcessor; +import com.sun.star.ucb.XContentIdentifier; +import com.sun.star.ucb.XContentIdentifierFactory; + +import com.sun.star.sdbc.XRow; + +import com.sun.star.script.framework.browse.ProviderBrowseNode; +import com.sun.star.script.framework.browse.DialogFactory; + +import com.sun.star.deployment.XPackage; + + +import com.sun.star.document.XScriptInvocationContext; +import com.sun.star.frame.XTransientDocumentsDocumentContentFactory; +import com.sun.star.uno.TypeClass; + +public abstract class ScriptProvider + implements XScriptProvider, XBrowseNode, XPropertySet, XInvocation, + XInitialization, XTypeProvider, XServiceInfo, XNameContainer +{ + private final String[] __serviceNames = { + "com.sun.star.script.provider.ScriptProviderFor", + "com.sun.star.script.provider.LanguageScriptProvider" + }; + + public final static String CLASSPATH = "classpath"; + + protected String language; + + protected XComponentContext m_xContext; + protected XMultiComponentFactory m_xMultiComponentFactory; + protected XModel m_xModel; + protected XScriptInvocationContext m_xInvocContext; + protected ParcelContainer m_container; + + // proxies to helper objects which implement interfaces + private XPropertySet m_xPropertySetProxy; + private XInvocation m_xInvocationProxy; + // TODO should this be implemented in this class + private XBrowseNode m_xBrowseNodeProxy; + private XScriptContext m_xScriptContext; + + public ScriptProvider( XComponentContext ctx, String language ) + { + this.language = language; + __serviceNames[0] += language; + + LogUtils.DEBUG( "ScriptProvider: constructor - start. " + language ); + + m_xContext = ctx; + + // Initialize DialogFactory class in case dialogs are required + DialogFactory.createDialogFactory(m_xContext); + + try + { + m_xMultiComponentFactory = m_xContext.getServiceManager(); + + if ( m_xMultiComponentFactory == null ) + { + throw new Exception( "Error could not obtain a " + + "multicomponent factory - rethrowing Exception." ); + } + + Object serviceObj = m_xContext.getValueByName( + "/singletons/com.sun.star.util.theMacroExpander"); + + XMacroExpander me = (XMacroExpander) AnyConverter.toObject( + new Type(XMacroExpander.class), serviceObj); + + XMLParserFactory.setOfficeDTDURL(me.expandMacros( + "${$BRAND_BASE_DIR/program/bootstraprc::BaseInstallation}/share/dtd/officedocument/1_0/")); + + } + catch ( Exception e ) + { + LogUtils.DEBUG( LogUtils.getTrace( e ) ); + throw new com.sun.star.uno.RuntimeException( + "Error constructing ScriptProvider: " + + e.getMessage() ); + } + + LogUtils.DEBUG( "ScriptProvider: constructor - finished." ); + } + + synchronized public XScriptContext getScriptingContext() + { + if ( m_xScriptContext == null ) + { + m_xScriptContext = ScriptContext.createContext( m_xModel, m_xInvocContext, m_xContext, m_xMultiComponentFactory ); + } + return m_xScriptContext; + } + public void initialize( Object[] aArguments ) + throws com.sun.star.uno.Exception + { + LogUtils.DEBUG( "entering XInit for language " + language); + boolean isPkgProvider = false; + if( aArguments.length == 1 ) + { + String contextUrl = null; + if ( AnyConverter.getType(aArguments[0]).getTypeClass().equals(TypeClass.INTERFACE) ) + { + // try whether it denotes a XScriptInvocationContext + m_xInvocContext = (XScriptInvocationContext)UnoRuntime.queryInterface( + XScriptInvocationContext.class, aArguments[0]); + if ( m_xInvocContext != null ) + { + // if so, obtain the document - by definition, this must be + // the ScriptContainer + m_xModel = (XModel)UnoRuntime.queryInterface( XModel.class, + m_xInvocContext.getScriptContainer() ); + } + else + { + // otherwise, check whether it's an XModel + m_xModel = (XModel)UnoRuntime.queryInterface( XModel.class, + m_xInvocContext.getScriptContainer() ); + } + if ( m_xModel == null ) + { + throw new com.sun.star.uno.Exception( + "ScriptProvider argument must be either a string, a valid XScriptInvocationContext, " + + "or an XModel", this); + } + + contextUrl = getDocUrlFromModel( m_xModel ); + m_container = new ParcelContainer( m_xContext, contextUrl, language ); + } + else if (AnyConverter.isString(aArguments[0]) == true) + { + String originalContextURL = AnyConverter.toString(aArguments[0]); + LogUtils.DEBUG("creating Application, path: " + originalContextURL ); + contextUrl = originalContextURL; + // TODO no support for packages in documents yet + if ( originalContextURL.startsWith( "vnd.sun.star.tdoc" ) ) + { + m_container = new ParcelContainer( m_xContext, contextUrl, language ); + m_xModel = getModelFromDocUrl( originalContextURL ); + } + else + { + String extensionDb = null; + String extensionRepository = null; + if ( originalContextURL.startsWith( "bundled" ) ) + { + contextUrl = "vnd.sun.star.expand:$BUNDLED_EXTENSIONS"; + extensionDb = "vnd.sun.star.expand:${$BRAND_BASE_DIR/program/" + PathUtils.BOOTSTRAP_NAME + "::UserInstallation}/user"; + extensionRepository = "bundled"; + } + + if ( originalContextURL.startsWith( "share" ) ) + { + contextUrl = "vnd.sun.star.expand:${$BRAND_BASE_DIR/program/" + PathUtils.BOOTSTRAP_NAME + "::BaseInstallation}/share"; + extensionDb = "vnd.sun.star.expand:${$BRAND_BASE_DIR/program/" + PathUtils.BOOTSTRAP_NAME + "::UserInstallation}/user"; + extensionRepository = "shared"; + } + else if ( originalContextURL.startsWith( "user" ) ) + { + contextUrl = "vnd.sun.star.expand:${$BRAND_BASE_DIR/program/" + PathUtils.BOOTSTRAP_NAME + "::UserInstallation}/user"; + extensionDb = "vnd.sun.star.expand:${$BRAND_BASE_DIR/program/" + PathUtils.BOOTSTRAP_NAME + "::UserInstallation}/user"; + extensionRepository = "user"; + } + + if ( originalContextURL.endsWith( "uno_packages") ) + { + isPkgProvider = true; + } + if ( originalContextURL.endsWith( "uno_packages") && !originalContextURL.equals( contextUrl ) + && !extensionRepository.equals("bundled")) + { + contextUrl = PathUtils.make_url( contextUrl, "uno_packages" ); + } + if ( isPkgProvider ) + { + m_container = new UnoPkgContainer( m_xContext, contextUrl, extensionDb, extensionRepository, language ); + } + else + { + m_container = new ParcelContainer( m_xContext, contextUrl, language ); + } + } + } + else + { + throw new com.sun.star.uno.RuntimeException( + "ScriptProvider created with invalid argument"); + } + + LogUtils.DEBUG("Modified Application path is: " + contextUrl ); + LogUtils.DEBUG("isPkgProvider is: " + isPkgProvider ); + + // TODO should all be done in this class instead of + // deleagation???? + m_xBrowseNodeProxy = new ProviderBrowseNode( this, + m_container, m_xContext ); + + m_xInvocationProxy = (XInvocation)UnoRuntime.queryInterface(XInvocation.class, m_xBrowseNodeProxy); + m_xPropertySetProxy = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, m_xBrowseNodeProxy); + } + else + { + // this is ok, for example when executing a script from the + // command line + LogUtils.DEBUG( "ScriptProviderFor" + language + + " initialized without a context"); + } + LogUtils.DEBUG( "leaving XInit" ); + } + + /** + * Gets the types attribute of the ScriptProvider object + * + * @return The types value + */ + public com.sun.star.uno.Type[] getTypes() + { + Type[] retValue = new Type[ 8 ]; + retValue[ 0 ] = new Type( XScriptProvider.class ); + retValue[ 1 ] = new Type( XBrowseNode.class ); + retValue[ 2 ] = new Type( XInitialization.class ); + retValue[ 3 ] = new Type( XTypeProvider.class ); + retValue[ 4 ] = new Type( XServiceInfo.class ); + retValue[ 5 ] = new Type( XPropertySet.class ); + retValue[ 6 ] = new Type( XInvocation.class ); + retValue[ 7 ] = new Type( com.sun.star.container.XNameContainer.class ); + return retValue; + } + + /** + * Gets the implementationId attribute of the ScriptProvider object + * + * @return The implementationId value + */ + public byte[] getImplementationId() + { + return this.getClass().getName().getBytes(); + } + + /** + * Gets the implementationName attribute of the ScriptProvider object + * + * @return The implementationName value + */ + public String getImplementationName() + { + return getClass().getName(); + } + + /** + * Description of the Method + * + * @param serviceName Description of the Parameter + * @return Description of the Return Value + */ + public boolean supportsService( String serviceName ) + { + for ( int index = __serviceNames.length; index-- > 0; ) + { + if ( serviceName.equals( __serviceNames[ index ] ) ) + { + return true; + } + } + return false; + } + + /** + * Gets the supportedServiceNames attribute of the ScriptProvider object + * + * @return The supportedServiceNames value + */ + public String[] getSupportedServiceNames() + { + return __serviceNames; + } + + + + public abstract XScript getScript( /*IN*/String scriptURI ) + throws com.sun.star.uno.RuntimeException, + ScriptFrameworkErrorException; + + // TODO need to encapsulate this better, + // Some factory concept for creating/accessing Editor + // How this is passed down or how it is accessable by BrowseNode + // implementations needs thinking about + // This method is used to determine whether the ScriptProvider + // has a ScriptEditor + public abstract boolean hasScriptEditor(); + // TODO see above + // This method is used to get the ScriptEditor for this ScriptProvider + public abstract ScriptEditor getScriptEditor(); + + public ScriptMetaData getScriptData( /*IN*/String scriptURI ) throws ScriptFrameworkErrorException + + { + ParsedScriptUri details = null; + try + { + details = m_container.parseScriptUri( scriptURI ); + ScriptMetaData scriptData = m_container.findScript( details ); + if ( scriptData == null ) + { + throw new ScriptFrameworkErrorException( details.function + " does not exist", + null, details.function, language, ScriptFrameworkErrorType.NO_SUCH_SCRIPT ); + } + return scriptData; + } + catch ( com.sun.star.lang.IllegalArgumentException ila ) + { + // TODO specify the correct error Type + throw new ScriptFrameworkErrorException( ila.getMessage(), + null, scriptURI, language, ScriptFrameworkErrorType.UNKNOWN ); + } + catch ( com.sun.star.container.NoSuchElementException nse ) + { + throw new ScriptFrameworkErrorException( nse.getMessage(), + null, details.function, language, ScriptFrameworkErrorType.NO_SUCH_SCRIPT ); + } + catch ( com.sun.star.lang.WrappedTargetException wta ) + { + // TODO specify the correct error Type + Exception wrapped = (Exception)wta.TargetException; + String message = wta.getMessage(); + if ( wrapped != null ) + { + message = wrapped.getMessage(); + } + throw new ScriptFrameworkErrorException( message, + null, details.function, language, ScriptFrameworkErrorType.UNKNOWN ); + } + + } + + + // Implementation of XBrowseNode interface + public String getName() + { + return language; + } + + public XBrowseNode[] getChildNodes() + { + if ( m_xBrowseNodeProxy == null ) + { + LogUtils.DEBUG("No Nodes available "); + return new XBrowseNode[0]; + } + return m_xBrowseNodeProxy .getChildNodes(); + } + + public boolean hasChildNodes() + { + if ( m_xBrowseNodeProxy == null ) + { + LogUtils.DEBUG("No Nodes available "); + return false; + } + return m_xBrowseNodeProxy.hasChildNodes(); + } + + public short getType() + { + return BrowseNodeTypes.CONTAINER; + } + + public String toString() + { + return getName(); + } + + // implementation of XInvocation interface + public XIntrospectionAccess getIntrospection() { + return m_xInvocationProxy.getIntrospection(); + } + + public Object invoke(String aFunctionName, Object[] aParams, + short[][] aOutParamIndex, Object[][] aOutParam) + throws com.sun.star.lang.IllegalArgumentException, + com.sun.star.script.CannotConvertException, + com.sun.star.reflection.InvocationTargetException + { + return m_xInvocationProxy.invoke( + aFunctionName, aParams, aOutParamIndex, aOutParam); + } + + public void setValue(String aPropertyName, Object aValue) + throws com.sun.star.beans.UnknownPropertyException, + com.sun.star.script.CannotConvertException, + com.sun.star.reflection.InvocationTargetException + { + m_xInvocationProxy.setValue(aPropertyName, aValue); + } + + public Object getValue(String aPropertyName) + throws com.sun.star.beans.UnknownPropertyException + { + return m_xInvocationProxy.getValue(aPropertyName); + } + + public boolean hasMethod(String aName) { + return m_xInvocationProxy.hasMethod(aName); + } + + public boolean hasProperty(String aName) { + return m_xInvocationProxy.hasProperty(aName); + } + + public XPropertySetInfo getPropertySetInfo() + { + return m_xPropertySetProxy.getPropertySetInfo(); + } + + public void setPropertyValue(String aPropertyName, Object aValue) + throws com.sun.star.beans.UnknownPropertyException, + com.sun.star.beans.PropertyVetoException, + com.sun.star.lang.IllegalArgumentException, + com.sun.star.lang.WrappedTargetException + { + m_xPropertySetProxy.setPropertyValue(aPropertyName, aValue); + } + + public Object getPropertyValue(String PropertyName) + throws com.sun.star.beans.UnknownPropertyException, + com.sun.star.lang.WrappedTargetException + { + return m_xPropertySetProxy.getPropertyValue(PropertyName); + } + + public void addPropertyChangeListener( + String aPropertyName, XPropertyChangeListener xListener) + throws com.sun.star.beans.UnknownPropertyException, + com.sun.star.lang.WrappedTargetException + { + m_xPropertySetProxy.addPropertyChangeListener(aPropertyName, xListener); + } + + public void removePropertyChangeListener( + String aPropertyName, XPropertyChangeListener aListener) + throws com.sun.star.beans.UnknownPropertyException, + com.sun.star.lang.WrappedTargetException + { + m_xPropertySetProxy.removePropertyChangeListener( + aPropertyName, aListener); + } + + public void addVetoableChangeListener( + String PropertyName, XVetoableChangeListener aListener) + throws com.sun.star.beans.UnknownPropertyException, + com.sun.star.lang.WrappedTargetException + { + m_xPropertySetProxy.addVetoableChangeListener(PropertyName, aListener); + } + + public void removeVetoableChangeListener( + String PropertyName, XVetoableChangeListener aListener) + throws com.sun.star.beans.UnknownPropertyException, + com.sun.star.lang.WrappedTargetException + { + m_xPropertySetProxy.removeVetoableChangeListener( + PropertyName, aListener); + } + public java.lang.Object getByName( String aName ) throws com.sun.star.container.NoSuchElementException, com.sun.star.lang.WrappedTargetException + { + // TODO needs implementing? + if ( true ) + { + throw new com.sun.star.uno.RuntimeException( + "getByName not implemented" ); + } + return new Object(); + } + + public String[] getElementNames() + { + // TODO needs implementing? + String[] result = new String[0]; + if ( true ) + { + throw new com.sun.star.uno.RuntimeException( + "getElementNames not implemented" ); + + } + return result; + } + + + // Performs the getRegStatus functionality for the PkgMgr + public boolean hasByName( String aName ) + { + boolean result = false; + if ( ((UnoPkgContainer)m_container).hasRegisteredUnoPkgContainer( aName ) ) + { + result = true; + } + return result; + } + + public com.sun.star.uno.Type getElementType() + { + // TODO at the moment this returns void indicating + // type is unknown should indicate XPackage ? do we implement XPackage + return new Type(); + } + + public boolean hasElements() + { + // TODO needs implementing? + boolean result = false; + if ( true ) + { + throw new com.sun.star.uno.RuntimeException( + "hasElements not implemented" ); + + } + return result; + } + public void replaceByName( String aName, java.lang.Object aElement ) throws com.sun.star.lang.IllegalArgumentException, com.sun.star.container.NoSuchElementException, com.sun.star.lang.WrappedTargetException + { + // TODO needs implementing + if ( true ) + { + throw new com.sun.star.uno.RuntimeException( + "replaceByName not implemented" ); + + } + } + + public void insertByName( String aName, java.lang.Object aElement ) throws com.sun.star.lang.IllegalArgumentException, com.sun.star.container.ElementExistException, com.sun.star.lang.WrappedTargetException + { + LogUtils.DEBUG("Provider for " + language + " received register for package " + aName ); + XPackage newPackage = ( XPackage ) UnoRuntime.queryInterface( XPackage.class, aElement ); + if ( aName.length() == 0 ) + { + throw new com.sun.star.lang.IllegalArgumentException( "Empty name" ); + } + if ( newPackage == null ) + { + throw new com.sun.star.lang.IllegalArgumentException( "No package supplied" ); + } + + ((UnoPkgContainer)m_container).processUnoPackage( newPackage, language ); + } + + // de-register for library only !! + public void removeByName( String Name ) throws com.sun.star.container.NoSuchElementException, com.sun.star.lang.WrappedTargetException + { + LogUtils.DEBUG("In ScriptProvider.removeByName() for " + Name + " this provider = " + language ); + ParcelContainer c = ((UnoPkgContainer)m_container).getRegisteredUnoPkgContainer( Name ); + if ( c != null ) + { + String libName; + if (Name.endsWith("/")) + { + String tmp = Name.substring( 0, Name.lastIndexOf( "/" ) ); + libName = tmp.substring( tmp.lastIndexOf( "/" ) + 1 ); + } + else + { + libName = Name.substring( Name.lastIndexOf( "/" ) + 1 ); + } + LogUtils.DEBUG("Deregistering library " + libName ); + if ( c.removeParcel( libName ) ) + { + ((UnoPkgContainer)m_container).deRegisterPackageContainer( Name ); + } + else + { + throw new com.sun.star.container.NoSuchElementException( libName + " cannot be removed from container." ); + } + } + else + { + throw new com.sun.star.container.NoSuchElementException( Name + " doesn't exist for " + language ); + } + // TODO see if we want to remove the ParcelContainer is no Parcels/Libraries left + } + + private String getDocUrlFromModel( XModel document ) + { + XTransientDocumentsDocumentContentFactory factory = null; + try + { + factory = (XTransientDocumentsDocumentContentFactory)UnoRuntime.queryInterface( + XTransientDocumentsDocumentContentFactory.class, + m_xMultiComponentFactory.createInstanceWithContext( + "com.sun.star.frame.TransientDocumentsDocumentContentFactory", + m_xContext + ) + ); + } + catch (Exception ex) + { + } + + if ( factory == null ) + throw new com.sun.star.uno.RuntimeException( "ScriptProvider: unable to create a TDOC context factory.", this ); + + try + { + XContent content = factory.createDocumentContent( document ); + return content.getIdentifier().getContentIdentifier(); + } + catch( Exception ex ) + { + } + + LogUtils.DEBUG("unable to determine the model's TDOC URL"); + return ""; + } + + private XModel getModelFromDocUrl( String docUrl ) + { + LogUtils.DEBUG("getModelFromDocUrl - searching for match for ->" + docUrl + "<-" ); + XModel xModel = null; + try + { + Object[] args = new String[] {"Local", "Office" }; + + Object ucb = m_xMultiComponentFactory.createInstanceWithArgumentsAndContext( "com.sun.star.ucb.UniversalContentBroker", args, m_xContext ); + + + XContentIdentifierFactory xFac = ( XContentIdentifierFactory ) + UnoRuntime.queryInterface( XContentIdentifierFactory.class, + ucb ); + + + XContentIdentifier xCntId = xFac.createContentIdentifier( docUrl ); + + + XContentProvider xCntAccess = ( XContentProvider ) + UnoRuntime.queryInterface( XContentProvider.class, + ucb ); + + + XContent xCnt = xCntAccess.queryContent( xCntId ); + + + XCommandProcessor xCmd = ( XCommandProcessor ) + UnoRuntime.queryInterface( XCommandProcessor.class, xCnt ); + + + Property[] pArgs = new Property[ ] { new Property() }; + pArgs[ 0 ].Name = "DocumentModel"; + pArgs[ 0 ].Handle = -1; + + Command command = new Command(); + + command.Handle = -1; + command.Name = "getPropertyValues"; + command.Argument = pArgs; + + com.sun.star.ucb.XCommandEnvironment env = null ; + Object result = xCmd.execute( command, 0, env ) ; + + XRow values = ( XRow ) UnoRuntime.queryInterface( XRow.class, + result ); + + xModel = ( XModel ) UnoRuntime.queryInterface( XModel.class, + values.getObject( 1, null ) ); + } + catch ( Exception ignore ) + { + LogUtils.DEBUG("Failed to get model exception " + ignore ); + + } + return xModel; + } + + +} 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; diff --git a/scripting/java/com/sun/star/script/framework/provider/java/Resolver.java b/scripting/java/com/sun/star/script/framework/provider/java/Resolver.java new file mode 100755 index 000000000000..548425ca3e44 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/provider/java/Resolver.java @@ -0,0 +1,50 @@ +/************************************************************************* + * + * 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.java; + +/** + * The Resolver interface is an interface common to all classes which + * want to implement an algorithm for obtaining a ScriptProxy object + * for a particular ScriptDescriptor and Class + * + * @author Tomas O'Connor + * @created August 2, 2002 + */ + +public interface Resolver { + /** + * Returns a ScriptProxy object for the given ScriptDescriptor and Class + * + * @param sd A script Descriptor + * @param c A Class + * @return The ScriptProxy value + */ + public ScriptProxy getProxy( ScriptDescriptor sd, Class c ) + throws NoSuchMethodException; +} + diff --git a/scripting/java/com/sun/star/script/framework/provider/java/ScriptDescriptor.java b/scripting/java/com/sun/star/script/framework/provider/java/ScriptDescriptor.java new file mode 100755 index 000000000000..59e9952b5837 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/provider/java/ScriptDescriptor.java @@ -0,0 +1,212 @@ +/************************************************************************* +* + * 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.java; + +import java.util.Vector; +import java.util.StringTokenizer; + +/** + * The <code>ScriptDescriptor</code> object is used to store the search + * criteria that should be used for finding a particular script + * + * @author Tomas O'Connor + * @created August 2, 2002 + */ +public class ScriptDescriptor +{ + private String m_name; + private String m_methodName; + private String m_className; + private Vector m_classpath; + private Vector m_argumentTypes = new Vector( 11 ); + + + /** + * Constructs a ScriptDescriptor for the given name + * + * @param name Script Name + * @exception IllegalArgumentException if the given name does not contain a "." + */ + public ScriptDescriptor( String name ) + throws IllegalArgumentException + { + int idx = name.lastIndexOf( '.' ); + + if ( idx == -1 ) + { + throw new IllegalArgumentException( "Invalid method name" ); + } + + this.m_name = name; + this.m_methodName = name.substring( idx + 1 ); + this.m_className = name.substring( 0, idx ); + } + + + /** + * Gets the fully qualified name of this <code>ScriptDescriptor</code> + * + * @return The Script Name value + */ + public String getName() + { + return m_name; + } + + /** + * Gets the fully qualified name of this <code>ScriptDescriptor</code> + * + * @return The Script Name value + */ + public String getClassName() + { + return m_className; + } + + + /** + * Gets the method name of this <code>ScriptDescriptor</code> + * + * @return The methodName value + */ + public String getMethodName() + { + return m_methodName; + } + + + /** + * Sets the classpath value stored by this <code>ScriptDescriptor</code> + * + * @param classpath The new classpath value + */ + public void setClasspath( String classpath ) + { + StringTokenizer stk = new StringTokenizer( classpath, ":" ); + while( stk.hasMoreElements() ) + { + this.m_classpath.add( (String) stk.nextElement() ); + } + } + + /** + * Sets the classpath value stored by this <code>ScriptDescriptor</code> + * + * @param classpath The new classpath value + */ + public void setClasspath( Vector classpath ) + { + this.m_classpath = classpath; + } + + + /** + * Gets the classpath value stored by this <code>ScriptDescriptor</code> + * + * @return The classpath value + */ + public Vector getClasspath() + { + return m_classpath; + } + + + /** + * Adds the given <code>Class</code> to the list of argument types stored in + * this ScriptDescriptor + * + * @param clazz The feature to be added to the ArgumentType attribute + */ + public synchronized void addArgumentType( Class clazz ) + { + m_argumentTypes.addElement( clazz ); + } + + + /** + * Adds the given array of <code>Class</code> to the list of argument types + * stored in this ScriptDescriptor + * + * @param classes The feature to be added to the ArgumentTypes attribute + */ + public synchronized void addArgumentTypes( Class[] classes ) + { + for ( int i = 0; i < classes.length; i++ ) + { + addArgumentType( classes[ i ] ); + } + } + + + /** + * Gets a list of the types of the arguments stored in this + * <code>ScriptDescriptor</code> + * + * return the argument types as an array of Class + * + * @return The argumentTypes value + */ + public synchronized Class[] + getArgumentTypes() + { + if ( m_argumentTypes.size() > 0 ) + return ( Class[] ) m_argumentTypes.toArray( new Class[ 0 ] ); + else + return null; + } + + + /** + * Returns a <code>String</code> representation of this + * <code>ScriptDescriptor</code> + * + * @return The scriptName including the parameters. + */ + public String toString() + { + StringBuffer description = new StringBuffer( m_name ); + Class[] types = getArgumentTypes(); + + description.append( " (" ); + + if ( types != null ) + { + for ( int i = 0; i < types.length - 1; i++ ) + { + description.append( types[ i ].getName() ); + description.append( ", " ); + } + + description.append( types[ types.length - 1 ].getName() ); + } + description.append( ")" ); + + return description.toString(); + } +} + diff --git a/scripting/java/com/sun/star/script/framework/provider/java/ScriptProviderForJava.java b/scripting/java/com/sun/star/script/framework/provider/java/ScriptProviderForJava.java new file mode 100755 index 000000000000..707ea05624d9 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/provider/java/ScriptProviderForJava.java @@ -0,0 +1,364 @@ +/************************************************************************* +* + * 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.java; + +import com.sun.star.frame.XModel; +import com.sun.star.comp.loader.FactoryHelper; +import com.sun.star.document.XScriptInvocationContext; +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.uno.Type; +import com.sun.star.uno.Any; + +import java.util.ArrayList; +import java.util.Map; +import java.net.MalformedURLException; + +import com.sun.star.script.provider.XScriptContext; +import com.sun.star.script.provider.XScript; +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.container.ScriptMetaData; + +import com.sun.star.script.framework.provider.*; +import com.sun.star.script.framework.log.LogUtils; +/** + * Description of the Class + * + * @author Noel Power + * @created August 2, 2002 + */ +public class ScriptProviderForJava +{ + /** + * Description of the Class + * + * @author Noel Power + * @created August 2, 2002 + */ + public static class _ScriptProviderForJava extends ScriptProvider + { + private Resolver m_resolutionPolicy = new StrictResolver(); + + public _ScriptProviderForJava( XComponentContext ctx ) + { + super (ctx, "Java"); + } + + public XScript getScript( /*IN*/String scriptURI ) + throws com.sun.star.uno.RuntimeException, + ScriptFrameworkErrorException + { + ScriptMetaData scriptData = null; + scriptData = getScriptData( scriptURI ); + ScriptImpl script = null; + try + { + script = new ScriptImpl( m_xContext, m_resolutionPolicy, 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 false; + } + + public ScriptEditor getScriptEditor() + { + return null; + } + } + + /** + * 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( ScriptProviderForJava._ScriptProviderForJava.class.getName() ) ) + { + xSingleServiceFactory = FactoryHelper.getServiceFactory( + ScriptProviderForJava._ScriptProviderForJava.class, + "com.sun.star.script.provider.ScriptProviderForJava", + multiFactory, + regKey ); + } + + return xSingleServiceFactory; + } +} + +class ScriptImpl implements XScript +{ + private ScriptMetaData metaData; + private XComponentContext m_xContext; + private XModel m_xModel; + private XScriptInvocationContext m_xInvocContext; + private XMultiComponentFactory m_xMultiComponentFactory; + private Resolver m_resolutionPolicy; + ScriptImpl( XComponentContext ctx, Resolver resolver, ScriptMetaData metaData, XModel xModel, XScriptInvocationContext xInvocContext ) throws com.sun.star.uno.RuntimeException + { + this.metaData = metaData; + this.m_xContext = ctx; + this.m_xModel = xModel; + this.m_xInvocContext = xInvocContext; + this.m_resolutionPolicy = resolver; + try + { + this.m_xMultiComponentFactory = m_xContext.getServiceManager(); + } + catch ( Exception e ) + { + LogUtils.DEBUG( LogUtils.getTrace( e ) ); + throw new com.sun.star.uno.RuntimeException( + "Error constructing ScriptProvider: " + + e.getMessage() ); + } + + LogUtils.DEBUG("ScriptImpl [java] script data = " + metaData ); + } + /** + * Invoke + * + * + * @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[] params, + /*OUT*/short[][] aOutParamIndex, + /*OUT*/Object[][] aOutParam ) + + throws ScriptFrameworkErrorException, com.sun.star.reflection.InvocationTargetException + { + LogUtils.DEBUG( "** ScriptProviderForJava::invoke: Starting..." ); + + // Initialise the out paramters - not used at the moment + aOutParamIndex[0] = new short[0]; + aOutParam[0] = new Object[0]; + + + Map languageProps = metaData.getLanguageProperties(); + + ScriptDescriptor scriptDesc = + new ScriptDescriptor( metaData.getLanguageName() ); + + ClassLoader scriptLoader = null; + + try { + LogUtils.DEBUG( "Classloader starting..." ); + scriptLoader = ClassLoaderFactory.getURLClassLoader( + metaData ); + LogUtils.DEBUG( "Classloader finished..." ); + } + catch (MalformedURLException mfe ) + { + // Framework error + throw new ScriptFrameworkErrorException( + mfe.getMessage(), null, + metaData.getLanguageName(), metaData.getLanguage(), + ScriptFrameworkErrorType.MALFORMED_URL ); + } + catch (NoSuitableClassLoaderException ncl ) + { + // Framework error + throw new ScriptFrameworkErrorException( + ncl.getMessage(), null, + metaData.getLanguageName(), metaData.getLanguage(), + ScriptFrameworkErrorType.UNKNOWN ); + } + catch (ArrayStoreException e ) + { + // Framework error + throw new ScriptFrameworkErrorException( + e.getMessage(), null, + metaData.getLanguageName(), metaData.getLanguage(), + ScriptFrameworkErrorType.UNKNOWN ); + } + + ArrayList invocationArgList = new ArrayList(); + Object[] invocationArgs = null; + + LogUtils.DEBUG( "Parameter Mapping..." ); + + // Setup Context Object + XScriptContext xSc = ScriptContext.createContext(m_xModel, m_xInvocContext, + m_xContext, m_xMultiComponentFactory); + scriptDesc.addArgumentType( XScriptContext.class ); + invocationArgList.add( xSc ); + + for ( int i = 0; i < params.length; i++ ) + { + scriptDesc.addArgumentType( params[ i ].getClass() ); + invocationArgList.add( params[ i ] ); + } + + if ( !invocationArgList.isEmpty() ) + { + invocationArgs = invocationArgList.toArray(); + } + + + + LogUtils.DEBUG( "ScriptProxy starting... " ); + ScriptProxy script = null; + try + { + String className = metaData.getLanguageName().substring( 0, + metaData.getLanguageName().lastIndexOf( '.' ) ); + LogUtils.DEBUG( "About to load Class " + className + " starting... " ); + + long start = new java.util.Date().getTime(); + Class c = scriptLoader.loadClass( className ); + long end = new java.util.Date().getTime(); + + LogUtils.DEBUG("loadClass took: " + String.valueOf(end - start) + + "milliseconds"); + + try + { + LogUtils.DEBUG( "class loaded ... " ); + script = m_resolutionPolicy.getProxy( scriptDesc, c ); + LogUtils.DEBUG( "script resolved ... " ); + } + catch( NoSuchMethodException e ) + { + // Framework error + throw new ScriptFrameworkErrorException( + e.getMessage(), null, + metaData.getLanguageName(), metaData.getLanguage(), + ScriptFrameworkErrorType.NO_SUCH_SCRIPT ); + } + } + catch ( ClassNotFoundException e ) + { + // Framework error + throw new ScriptFrameworkErrorException( + e.getMessage(), null, + metaData.getLanguageName(), metaData.getLanguage(), + ScriptFrameworkErrorType.NO_SUCH_SCRIPT ); + } + + LogUtils.DEBUG( "Starting Invoke on Proxy ..." ); + Object result = null; + + try + { + long start = new java.util.Date().getTime(); + result = script.invoke( invocationArgs ); + long end = new java.util.Date().getTime(); + + LogUtils.DEBUG("invoke took: " + + String.valueOf(end - start) + "milliseconds"); + } + catch ( java.lang.IllegalArgumentException iae ) + { + throw new ScriptFrameworkErrorException( + iae.getMessage(), null, + metaData.getLanguageName(), metaData.getLanguage(), + ScriptFrameworkErrorType.UNKNOWN ); + + } + catch ( java.lang.IllegalAccessException ia ) + { + throw new ScriptFrameworkErrorException( + ia.getMessage(), null, + metaData.getLanguageName(), metaData.getLanguage(), + ScriptFrameworkErrorType.UNKNOWN ); + } + catch ( java.lang.reflect.InvocationTargetException ite ) + { + Throwable targetException = ite.getTargetException(); + ScriptExceptionRaisedException se = + new ScriptExceptionRaisedException( + targetException.toString() ); + se.lineNum = -1; + se.scriptName = metaData.getLanguageName(); + se.language = "Java"; + se.exceptionType = targetException.getClass().getName(); + throw new com.sun.star.reflection.InvocationTargetException( + "Scripting Framework error executing script ", null, se ); + } + catch ( Exception unknown ) + { + ScriptExceptionRaisedException se = + new ScriptExceptionRaisedException( + unknown.toString() ); + se.lineNum = -1; + se.scriptName = metaData.getLanguageName(); + se.language = "Java"; + se.exceptionType = unknown.getClass().getName(); + throw new com.sun.star.reflection.InvocationTargetException( + "Scripting Framework error executing script ", null, se ); + } + if ( result == null ) + { + LogUtils.DEBUG( "Got Nothing Back" ); + // in the case where there is no return type + Any voidAny = new Any(new Type(), null); + result = voidAny; + } + else + { + LogUtils.DEBUG( "Got object " + result ); + } + return result; + } +} diff --git a/scripting/java/com/sun/star/script/framework/provider/java/ScriptProxy.java b/scripting/java/com/sun/star/script/framework/provider/java/ScriptProxy.java new file mode 100755 index 000000000000..6cd36c83710f --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/provider/java/ScriptProxy.java @@ -0,0 +1,92 @@ +/************************************************************************* +* + * 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.java; + +import java.lang.reflect.Method; +import java.lang.reflect.InvocationTargetException; + +/** + * A ScriptProxy object acts as a proxy for a Java <code>Method</code> + * + * @author Tomas O'Connor + * @created August 2, 2002 + * @see java.lang.reflect.Method + */ +public class ScriptProxy +{ + private Object m_targetObject; + private Method m_method; + + + /** + * Constructs a <code>ScriptProxy</code> object for the given + * <code>Method</code> + * + * @param method Description of the Parameter + */ + public ScriptProxy( Method method ) + { + this.m_method = method; + } + + + /** + * Sets the <code>Object</code> on which the ScriptProxy should invoke + * the method + * + * @param obj The new targetObject value + */ + public void setTargetObject( Object obj ) + { + m_targetObject = obj; + } + + + /** + * Invokes the method contained in this <code>ScriptProxy</code>, + * any exceptions resulting from the invocation will be thrown + * + * @param args the arguments to be passed when invoking + * the method + * @return the Object returned from the method + * invocation, may be null + * @exception IllegalAccessException Description of the Exception + * @exception InvocationTargetException Description of the Exception + * @exception IllegalArgumentException Description of the Exception + * @exception Exception Description of the Exception + * @see java.lang.reflect.Method for the exceptions + * that may be thrown + */ + public Object invoke( Object[] args ) + throws IllegalAccessException, InvocationTargetException, + IllegalArgumentException + { + return m_method.invoke( m_targetObject, args ); + } +} + diff --git a/scripting/java/com/sun/star/script/framework/provider/java/StrictResolver.java b/scripting/java/com/sun/star/script/framework/provider/java/StrictResolver.java new file mode 100755 index 000000000000..8adb6e66e5e8 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/provider/java/StrictResolver.java @@ -0,0 +1,128 @@ +/************************************************************************* +* + * 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.java; + +import java.lang.reflect.*; +import com.sun.star.script.framework.log.LogUtils; + +/** + * A StrictResolver can be used to get a ScriptProxy object for a given + * ScriptDescriptor and Class. The StrictResolver is an implementation of + * the Resolver strategy. It will only return a ScriptProxy object if a + * method accepting all of the arguments specified in the ScriptDescriptor + * can be found in the Class. + * + * @author Tomas O'Connor + * @created August 2, 2002 + */ +public class StrictResolver implements Resolver +{ + /** + *Constructor for the StrictResolver object + */ + public StrictResolver() + { + LogUtils.DEBUG( this.getClass().getName() + " created" ); + } + + + /** + * Returns a ScriptProxy object for the given ScriptDescriptor and Class. + * Only a strict match will be returned ie. where all of the arguments in + * the given ScriptDescriptor match the types of the + * + * @param sd the ScriptDescriptor for which a ScriptProxy is required + * @param c the Class file in which to search for the method + * @return the ScriptProxy matching the criteria, or null if no match is found + */ + public ScriptProxy getProxy( ScriptDescriptor sd, Class c ) + throws NoSuchMethodException + { + Method m = null; + ScriptProxy sp = null; + + LogUtils.DEBUG( "StrictResolver.getProxy() for: " + sd.toString() ); + + try + { + m = resolveArguments( sd, c ); + } + catch ( ClassNotFoundException e ) + { + throw new NoSuchMethodException( "StrictResolver.getProxy: Cant find method: " + + sd.getMethodName() + ":" + e.getMessage() ); + } + catch ( NoSuchMethodException e ) + { + throw new NoSuchMethodException( "StrictResolver.getProxy: Cant find method: " + + sd.getMethodName() + ":" + e.getMessage() ); + } + + sp = new ScriptProxy( m ); + + int modifiers = m.getModifiers(); + if ( !Modifier.isStatic( modifiers ) ) + { + Object o; + try + { + o = c.newInstance(); + } + catch ( InstantiationException ie ) + { + throw new NoSuchMethodException( "getScriptProxy: Cant instantiate: " + + c.getName() ); + } + catch ( IllegalAccessException iae ) + { + throw new NoSuchMethodException( "getScriptProxy: Cant access: " + + c.getName() ); + } + sp.setTargetObject( o ); + } + + return sp; + } + + + /** + * Description of the Method + * + * @param sd Description of the Parameter + * @param c Description of the Parameter + * @return Description of the Return Value + * @exception ClassNotFoundException + * @exception NoSuchMethodException + */ + private Method resolveArguments( ScriptDescriptor sd, Class c ) + throws ClassNotFoundException, NoSuchMethodException + { + return c.getMethod( sd.getMethodName(), sd.getArgumentTypes() ); + } +} + diff --git a/scripting/java/com/sun/star/script/framework/provider/javascript/ScriptEditorForJavaScript.java b/scripting/java/com/sun/star/script/framework/provider/javascript/ScriptEditorForJavaScript.java new file mode 100644 index 000000000000..b9849d1e4e1d --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/provider/javascript/ScriptEditorForJavaScript.java @@ -0,0 +1,376 @@ +/************************************************************************* + * + * 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.javascript; + +import org.mozilla.javascript.Context; +import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ImporterTopLevel; +import org.mozilla.javascript.tools.debugger.Main; +import org.mozilla.javascript.tools.debugger.ScopeProvider; + +import com.sun.star.script.provider.XScriptContext; +import com.sun.star.script.framework.container.ScriptMetaData; +import com.sun.star.script.framework.provider.ScriptEditor; +import com.sun.star.script.framework.log.LogUtils; + +import java.io.InputStream; +import java.io.IOException; +import java.net.URL; + +import java.util.Map; +import java.util.HashMap; + +import javax.swing.SwingUtilities; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +public class ScriptEditorForJavaScript implements ScriptEditor +{ + // global ScriptEditorForJavaScript instance + private static ScriptEditorForJavaScript theScriptEditorForJavaScript; + + // template for JavaScript scripts + private static String JSTEMPLATE; + + static private Main rhinoWindow; + private URL scriptURL; + // global list of ScriptEditors, key is URL of file being edited + private static Map BEING_EDITED = new HashMap(); + + static { + try { + URL url = + ScriptEditorForJavaScript.class.getResource("template.js"); + + 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(); + + JSTEMPLATE = buf.toString(); + } + catch (IOException ioe) { + JSTEMPLATE = "// JavaScript script"; + } + catch (Exception e) { + JSTEMPLATE = "// JavaScript script"; + } + } + + /** + * Returns the global ScriptEditorForJavaScript instance. + */ + public static ScriptEditorForJavaScript getEditor() + { + if (theScriptEditorForJavaScript == null) + { + synchronized(ScriptEditorForJavaScript.class) + { + if (theScriptEditorForJavaScript == null) + { + theScriptEditorForJavaScript = + new ScriptEditorForJavaScript(); + } + } + } + return theScriptEditorForJavaScript; + } + + /** + * Get the ScriptEditorForJavaScript instance for this URL + * + * @param url The URL of the script source file + * + * @return The ScriptEditorForJavaScript associated with + * the given URL if one exists, otherwise null. + */ + public static ScriptEditorForJavaScript getEditor(URL url) + { + return (ScriptEditorForJavaScript)BEING_EDITED.get(url); + } + + /** + * Returns whether or not the script source being edited in this + * ScriptEditorForJavaScript has been modified + */ + public boolean isModified() + { + return rhinoWindow.isModified( scriptURL ); + } + + /** + * Returns the text being displayed in this ScriptEditorForJavaScript + * + * @return The text displayed in this ScriptEditorForJavaScript + */ + public String getText() + { + return rhinoWindow.getText( scriptURL ); + } + + /** + * Returns the Rhino Debugger url of this ScriptEditorForJavaScript + * + * @return The url of this ScriptEditorForJavaScript + */ + public String getURL() + { + return scriptURL.toString(); + } + + /** + * Returns the template text for JavaScript scripts + * + * @return The template text for JavaScript scripts + */ + public String getTemplate() + { + return JSTEMPLATE; + } + + /** + * Returns the default extension for JavaScript scripts + * + * @return The default extension for JavaScript scripts + */ + public String getExtension() + { + return "js"; + } + + /** + * 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(final XScriptContext context, ScriptMetaData entry) + { + try { + 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)) + if ( rhinoWindow != null ) + { + ScriptEditorForJavaScript editor = + (ScriptEditorForJavaScript) BEING_EDITED.get(url); + if ( editor == null ) + { + editor = new ScriptEditorForJavaScript( context, url ); + editor.edit( context, entry ); + } + else + { + rhinoWindow.showScriptWindow( url ); + } + } + else + { + ScriptEditorForJavaScript editor = + new ScriptEditorForJavaScript( context, url ); + + } + rhinoWindow.toFront(); + } + catch ( IOException e ) + { + LogUtils.DEBUG("Caught exception: " + e); + LogUtils.DEBUG(LogUtils.getTrace(e)); + } + } + + // Ensures that new instances of this class can only be created using + // the factory methods + private ScriptEditorForJavaScript() + { + } + + private ScriptEditorForJavaScript(XScriptContext context, URL url) + { + initUI(); + Scriptable scope = getScope( context ); + this.rhinoWindow.openFile(url, scope, new closeHandler( url ) ); + + + this.scriptURL = url; + synchronized( ScriptEditorForJavaScript.class ) + { + BEING_EDITED.put(url, this); + } + + } + + /** + * Executes the script edited by the editor + * + */ + + public Object execute() throws Exception + { + rhinoWindow.toFront(); + + return this.rhinoWindow.runScriptWindow( scriptURL ); + } + + /** + * Indicates the line where error occured + * + */ + public void indicateErrorLine( int lineNum ) + { + this.rhinoWindow.toFront(); + this.rhinoWindow.highlighLineInScriptWindow( scriptURL, lineNum ); + } + // This code is based on the main method of the Rhino Debugger Main class + // We pass in the XScriptContext in the global scope for script execution + private void initUI() { + try { + synchronized ( ScriptEditorForJavaScript.class ) + { + if ( this.rhinoWindow != null ) + { + return; + } + + final Main sdb = new Main("Rhino JavaScript Debugger"); + swingInvoke(new Runnable() { + public void run() { + sdb.pack(); + sdb.setSize(640, 640); + sdb.setVisible(true); + } + }); + sdb.setExitAction(new Runnable() { + public void run() { + sdb.clearAllBreakpoints(); + sdb.dispose(); + shutdown(); + } + }); + Context.addContextListener(sdb); + sdb.setScopeProvider(new ScopeProvider() { + public Scriptable getScope() { + return org.mozilla.javascript.tools.shell.Main.getScope(); + } + }); + sdb.addWindowListener( new WindowAdapter() { + public void windowClosing(WindowEvent e) { + shutdown(); + } + }); + this.rhinoWindow = sdb; + } + } catch (Exception exc) { + LogUtils.DEBUG( LogUtils.getTrace( exc ) ); + } + } + + private static void swingInvoke(Runnable f) { + if (SwingUtilities.isEventDispatchThread()) { + f.run(); + return; + } + try { + SwingUtilities.invokeAndWait(f); + } catch (Exception exc) { + LogUtils.DEBUG( LogUtils.getTrace( exc ) ); + } + } + + private void shutdown() + { + // dereference Rhino Debugger window + this.rhinoWindow = null; + this.scriptURL = null; + // remove all scripts from BEING_EDITED + synchronized( BEING_EDITED ) + { + java.util.Iterator iter = BEING_EDITED.keySet().iterator(); + java.util.Vector keysToRemove = new java.util.Vector(); + while ( iter.hasNext() ) + { + + URL key = (URL)iter.next(); + keysToRemove.add( key ); + } + for ( int i=0; i<keysToRemove.size(); i++ ) + { + BEING_EDITED.remove( keysToRemove.elementAt( i ) ); + } + keysToRemove = null; + } + + } + private Scriptable getScope(XScriptContext xsctxt ) + { + Context ctxt = Context.enter(); + ImporterTopLevel scope = new ImporterTopLevel(ctxt); + + Scriptable jsCtxt = Context.toObject(xsctxt, scope); + scope.put("XSCRIPTCONTEXT", scope, jsCtxt); + + Scriptable jsArgs = Context.toObject( + new Object[0], scope); + scope.put("ARGUMENTS", scope, jsArgs); + + Context.exit(); + return scope; + } + + class closeHandler implements Runnable + { + URL url; + closeHandler( URL url ) + { + this.url = url; + } + public void run() + { + synchronized( BEING_EDITED ) + { + Object o = BEING_EDITED.remove( this.url ); + } + } + } +} diff --git a/scripting/java/com/sun/star/script/framework/provider/javascript/ScriptProviderForJavaScript.java b/scripting/java/com/sun/star/script/framework/provider/javascript/ScriptProviderForJavaScript.java new file mode 100755 index 000000000000..9f04d9105374 --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/provider/javascript/ScriptProviderForJavaScript.java @@ -0,0 +1,358 @@ +/************************************************************************* +* + * 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.javascript; + +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.frame.XModel; +import com.sun.star.registry.XRegistryKey; +import com.sun.star.comp.loader.FactoryHelper; + +import com.sun.star.document.XScriptInvocationContext; +import com.sun.star.reflection.InvocationTargetException; + +import java.net.URL; + +import com.sun.star.script.provider.XScript; + +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.log.LogUtils; +import com.sun.star.script.framework.provider.ScriptContext; +import com.sun.star.script.framework.provider.ClassLoaderFactory; +import com.sun.star.script.framework.provider.ScriptProvider; +import com.sun.star.script.framework.provider.ScriptEditor; +import com.sun.star.script.framework.container.ScriptMetaData; + +import org.mozilla.javascript.Context; +import org.mozilla.javascript.ImporterTopLevel; +import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.JavaScriptException; + +public class ScriptProviderForJavaScript +{ + public static class _ScriptProviderForJavaScript extends ScriptProvider + { + public _ScriptProviderForJavaScript(XComponentContext ctx) + { + super(ctx, "JavaScript"); + } + + 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 ScriptEditorForJavaScript.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( ScriptProviderForJavaScript._ScriptProviderForJavaScript.class.getName() ) ) + { + xSingleServiceFactory = FactoryHelper.getServiceFactory( + ScriptProviderForJavaScript._ScriptProviderForJavaScript.class, + "com.sun.star.script.provider.ScriptProviderForJavaScript", + 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 xInvocContext ) throws com.sun.star.uno.RuntimeException + { + this.metaData = metaData; + this.m_xContext = ctx; + this.m_xModel = xModel; + this.m_xInvocContext = xInvocContext; + 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: [javascript]"); + } + LogUtils.DEBUG("ScriptImpl [javascript] script data = " + metaData ); + } + + /** + * The invoke method of the ScriptProviderForJavaScript runs the + * JavaScript script specified in the URI + * + * + * + * @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 ScriptFrameworkErrorException If there is no matching script name + * + * + * @throws InvocationTargetException If the running script throws + * an exception this information + * is captured and rethrown as + * ScriptErrorRaisedException or + * ScriptExceptionRaisedException + */ + + public Object invoke( + /*IN*/Object[] params, + /*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 ) + { + throw new ScriptFrameworkErrorException( + mfu.getMessage(), null, + metaData.getLanguageName(), metaData.getLanguage(), + ScriptFrameworkErrorType.MALFORMED_URL ); + } + catch ( com.sun.star.script.framework.provider.NoSuitableClassLoaderException nsc ) + { + // Framework error + throw new ScriptFrameworkErrorException( + nsc.getMessage(), null, + metaData.getLanguageName(), metaData.getLanguage(), + ScriptFrameworkErrorType.UNKNOWN ); + } + Context ctxt = null; + + try + { + String editorURL = sourceUrl.toString(); + Object result = null; + String source = null; + ScriptEditorForJavaScript editor = + ScriptEditorForJavaScript.getEditor( + metaData.getSourceURL() ); + + if (editor != null) + { + editorURL = editor.getURL(); + result = editor.execute(); + if ( result != null && + result.getClass().getName().equals( "org.mozilla.javascript.Undefined" ) ) + { + // Always return a string + // TODO revisit + return Context.toString( result ); + } + + } + + if (editor != null && editor.isModified() == true) + { + LogUtils.DEBUG("GOT A MODIFIED SOURCE"); + source = editor.getText(); + } + else + { + metaData.loadSource(); + source = metaData.getSource(); + + } + + if ( source == null || source.length() == 0 ) { + throw new ScriptFrameworkErrorException( + "Failed to read source data for script", null, + metaData.getLanguageName(), metaData.getLanguage(), + ScriptFrameworkErrorType.UNKNOWN ); + } + + /* Set the context ClassLoader on the current thread to + be our custom ClassLoader. This is the suggested method + for setting up a ClassLoader to be used by the Rhino + interpreter + */ + if (cl != null) { + Thread.currentThread().setContextClassLoader(cl); + } + + // Initialize a Rhino Context object + ctxt = Context.enter(); + + /* The ImporterTopLevel ensures that importClass and + importPackage statements work in Javascript scripts + Make the XScriptContext available as a global variable + to the script + */ + ImporterTopLevel scope = new ImporterTopLevel(ctxt); + + Scriptable jsCtxt = Context.toObject( + ScriptContext.createContext( + m_xModel, m_xInvocContext, m_xContext, + m_xMultiComponentFactory), scope); + scope.put("XSCRIPTCONTEXT", scope, jsCtxt); + + Scriptable jsArgs = Context.toObject(params, scope); + scope.put("ARGUMENTS", scope, jsArgs); + + result = ctxt.evaluateString(scope, + source, "<stdin>", 1, null); + result = ctxt.toString(result); + return result; + } + catch (JavaScriptException jse) { + LogUtils.DEBUG( "Caught JavaScriptException exception for JavaScript type = " + jse.getClass() ); + String message = jse.getMessage(); + //int lineNo = jse.getLineNumber(); + Object wrap = jse.getValue(); + LogUtils.DEBUG( "\t message " + message ); + LogUtils.DEBUG( "\t wrapped type " + wrap.getClass() ); + LogUtils.DEBUG( "\t wrapped toString " + wrap.toString() ); + ScriptExceptionRaisedException se = new + ScriptExceptionRaisedException( message ); + se.lineNum = -1; + se.language = "JavaScript"; + se.scriptName = metaData.getLanguageName(); + se.exceptionType = wrap.getClass().getName(); + se.language = metaData.getLanguage(); + LogUtils.DEBUG( "ExceptionRaised exception " ); + LogUtils.DEBUG( "\t message " + se.getMessage() ); + LogUtils.DEBUG( "\t lineNum " + se.lineNum ); + LogUtils.DEBUG( "\t language " + se.language ); + LogUtils.DEBUG( "\t scriptName " + se.scriptName ); + raiseEditor( se.lineNum ); + throw new InvocationTargetException( "JavaScript uncaught exception" + metaData.getLanguageName(), null, se ); + } + catch (Exception ex) { + LogUtils.DEBUG("Caught Exception " + ex ); + LogUtils.DEBUG("rethrowing as ScriptFramework error" ); + throw new ScriptFrameworkErrorException( + ex.getMessage(), null, + metaData.getLanguageName(), metaData.getLanguage(), + ScriptFrameworkErrorType.UNKNOWN ); + } + finally { + if ( ctxt != null ) + { + Context.exit(); + } + } + } + + private void raiseEditor( int lineNum ) + { + ScriptEditorForJavaScript editor = null; + try + { + URL sourceUrl = metaData.getSourceURL(); + editor = ScriptEditorForJavaScript.getEditor( sourceUrl ); + if ( editor == null ) + { + editor = ScriptEditorForJavaScript.getEditor(); + editor.edit( + ScriptContext.createContext(m_xModel, m_xInvocContext, + m_xContext, m_xMultiComponentFactory), metaData ); + editor = ScriptEditorForJavaScript.getEditor( sourceUrl ); + } + if ( editor != null ) + { + System.out.println("** Have raised IDE for JavaScript, calling indicateErrorLine for line " + lineNum ); + editor.indicateErrorLine( lineNum ); + } + } + catch( Exception ignore ) + { + } + } +} + diff --git a/scripting/java/com/sun/star/script/framework/provider/javascript/template.js b/scripting/java/com/sun/star/script/framework/provider/javascript/template.js new file mode 100644 index 000000000000..d992791e647c --- /dev/null +++ b/scripting/java/com/sun/star/script/framework/provider/javascript/template.js @@ -0,0 +1,37 @@ +// Hello World in JavaScript +// 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/ + +importClass(Packages.com.sun.star.uno.UnoRuntime); +importClass(Packages.com.sun.star.text.XTextDocument); +importClass(Packages.com.sun.star.text.XText); +importClass(Packages.com.sun.star.text.XTextRange); +importClass(Packages.com.sun.star.frame.XModel); + +// Import XScriptContext class. An instance of this class is available +// to all JavaScript 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 +// + +oDoc = UnoRuntime.queryInterface(XModel,XSCRIPTCONTEXT.getInvocationContext()); +if ( !oDoc ) + oDoc = XSCRIPTCONTEXT.getDocument(); +xTextDoc = UnoRuntime.queryInterface(XTextDocument,oDoc); +xText = xTextDoc.getText(); +xTextRange = xText.getEnd(); +xTextRange.setString( "Hello World (in JavaScript)" ); |