blob: cca381f7b29f327ceea62b60c61fd024c0a0a971 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the 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(
"${$OOO_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:${$OOO_BASE_DIR/program/" + PathUtils.BOOTSTRAP_NAME + "::UserInstallation}/user";
extensionRepository = "bundled";
}
if ( originalContextURL.startsWith( "share" ) )
{
contextUrl = "vnd.sun.star.expand:${$OOO_BASE_DIR/program/" + PathUtils.BOOTSTRAP_NAME + "::BaseInstallation}/share";
extensionDb = "vnd.sun.star.expand:${$OOO_BASE_DIR/program/" + PathUtils.BOOTSTRAP_NAME + "::UserInstallation}/user";
extensionRepository = "shared";
}
else if ( originalContextURL.startsWith( "user" ) )
{
contextUrl = "vnd.sun.star.expand:${$OOO_BASE_DIR/program/" + PathUtils.BOOTSTRAP_NAME + "::UserInstallation}/user";
extensionDb = "vnd.sun.star.expand:${$OOO_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;
}
}