# *************************************************************
#
#  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.
#
# *************************************************************

# XScript implementation for python
import uno
import unohelper
import sys
import os
import types
import time
import ast

try:
    unicode
except NameError:
    unicode = str

class LogLevel:
    NONE = 0   # production level
    ERROR = 1  # for script developers
    DEBUG = 2  # for script framework developers

PYSCRIPT_LOG_ENV = "PYSCRIPT_LOG_LEVEL"
PYSCRIPT_LOG_STDOUT_ENV = "PYSCRIPT_LOG_STDOUT"

# Configuration ----------------------------------------------------
LogLevel.use = LogLevel.NONE
if os.environ.get(PYSCRIPT_LOG_ENV) == "ERROR":
    LogLevel.use = LogLevel.ERROR
elif os.environ.get(PYSCRIPT_LOG_ENV) == "DEBUG":
    LogLevel.use = LogLevel.DEBUG

# True, writes to stdout (difficult on windows)
# False, writes to user/Scripts/python/log.txt
LOG_STDOUT = os.environ.get(PYSCRIPT_LOG_STDOUT_ENV, "1") != "0"

#-------------------------------------------------------------------

def encfile(uni):
    if sys.version_info[0] > 2:
        return uni
    else:
        return uni.encode( sys.getfilesystemencoding())

def lastException2String():
    (excType,excInstance,excTraceback) = sys.exc_info()
    ret = str(excType) + ": "+str(excInstance) + "\n" + \
          uno._uno_extract_printable_stacktrace( excTraceback )
    return ret

def logLevel2String( level ):
    ret = " NONE"
    if level == LogLevel.ERROR:
        ret = "ERROR"
    elif level >= LogLevel.DEBUG:
        ret = "DEBUG"
    return ret

def getLogTarget():
    ret = sys.stdout
    if not LOG_STDOUT:
        try:
            pathSubst = uno.getComponentContext().ServiceManager.createInstance(
                "com.sun.star.util.PathSubstitution" )
            userInstallation =  pathSubst.getSubstituteVariableValue( "user" )
            if len( userInstallation ) > 0:
                systemPath = uno.fileUrlToSystemPath( userInstallation + "/Scripts/python/log.txt" )
                ret = open( systemPath , "a" )
        except Exception as e:
            print("Exception during creation of pythonscript logfile: "+ lastException2String() + "\n, delagating log to stdout\n")
    return ret

class Logger(LogLevel):
    def __init__(self , target ):
        self.target = target

    def isDebugLevel( self ):
        return self.use >= self.DEBUG

    def debug( self, msg ):
        if self.isDebugLevel():
            self.log( self.DEBUG, msg )

    def isErrorLevel( self ):
        return self.use >= self.ERROR

    def error( self, msg ):
        if self.isErrorLevel():
            self.log( self.ERROR, msg )

    def log( self, level, msg ):
        if self.use >= level:
            try:
                self.target.write(
                    time.asctime() +
                    " [" +
                    logLevel2String( level ) +
                    "] " +
                    encfile(msg) +
                    "\n" )
                self.target.flush()
            except Exception as e:
                print("Error during writing to stdout: " +lastException2String() + "\n")

log = Logger( getLogTarget() )

log.debug( "pythonscript loading" )

#from com.sun.star.lang import typeOfXServiceInfo, typeOfXTypeProvider
from com.sun.star.uno import RuntimeException
from com.sun.star.lang import XServiceInfo
from com.sun.star.io import IOException, XInputStream
from com.sun.star.ucb import CommandAbortedException, XCommandEnvironment, XProgressHandler, Command
from com.sun.star.task import XInteractionHandler
from com.sun.star.beans import XPropertySet, Property
from com.sun.star.container import XNameContainer
from com.sun.star.xml.sax import XDocumentHandler, InputSource
from com.sun.star.uno import Exception as UnoException
from com.sun.star.script import XInvocation
from com.sun.star.awt import XActionListener, FontDescriptor
from com.sun.star.awt.FontPitch import FIXED

from com.sun.star.script.provider import XScriptProvider, XScript, XScriptContext, ScriptFrameworkErrorException
from com.sun.star.script.browse import XBrowseNode
from com.sun.star.script.browse.BrowseNodeTypes import SCRIPT, CONTAINER, ROOT
from com.sun.star.util import XModifyListener

LANGUAGENAME = "Python"
GLOBAL_SCRIPTCONTEXT_NAME = "XSCRIPTCONTEXT"
CALLABLE_CONTAINER_NAME =  "g_exportedScripts"

# pythonloader looks for a static g_ImplementationHelper variable
g_ImplementationHelper = unohelper.ImplementationHelper()
g_implName = "org.openoffice.pyuno.LanguageScriptProviderFor"+LANGUAGENAME



BLOCK_SIZE = 65536
def readTextFromStream( inputStream ):
    # read the file
    code = uno.ByteSequence( b"" )
    while True:
        read,out = inputStream.readBytes( None , BLOCK_SIZE )
        code = code + out
        if read < BLOCK_SIZE:
            break
    if sys.version_info[0] > 2:
        return str( code.value, 'utf-8' )
    else:
        return code.value

def toIniName( str ):
    # TODO: what is the official way to get to know whether i am on the windows platform ?
    if( hasattr(sys , "dllhandle") ):
        return str + ".ini"
    return str + "rc"

class EmptyInputStream( unohelper.Base, XInputStream ):
    def __init__( self ):
        pass

    def closeInput(self):
        pass

    def readBytes( self, seq, n ):
        return 0, ""

    def readSomeBytes( self, seq, n ):
        return 0, ""

    def skipBytes( self, n ):
        pass

    def available( self ):
        return 0

class BytesInputStream( unohelper.Base, XInputStream ):
    def __init__( self, bytes ):
        self.bytes = bytes
        self.position = 0

    def closeInput(self):
        pass

    def readBytes( self, seq, n ):
        size = self.available()
        if n < size:
            size = n
        curr = self.position
        self.position += size
        return size, uno.ByteSequence( self.bytes[curr:curr+size] )

    def readSomeBytes( self, seq, n ):
        return self.readBytes( seq, n )

    def skipBytes( self, n ):
        size = self.available()
        if n < size:
            size = n
        self.position += size

    def available( self ):
        return len( self.bytes ) - self.position

""" definition: storageURI is the system dependent, absolute file url, where the script is stored on disk
                scriptURI is the system independent uri
"""
class MyUriHelper:

    def __init__( self, ctx, location ):
        self.s_UriMap = \
        { "share" : "vnd.sun.star.expand:${$OOO_BASE_DIR/program/" +  toIniName( "bootstrap") + "::BaseInstallation}/share/Scripts/python" , \
          "share:uno_packages" : "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE/uno_packages", \
          "user" : "vnd.sun.star.expand:${$OOO_BASE_DIR/program/" + toIniName( "bootstrap") + "::UserInstallation}/user/Scripts/python" , \
          "user:uno_packages" : "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/uno_packages" }
        self.m_uriRefFac = ctx.ServiceManager.createInstanceWithContext("com.sun.star.uri.UriReferenceFactory",ctx)
        if location.startswith( "vnd.sun.star.tdoc" ):
            self.m_baseUri = location + "/Scripts/python"
            self.m_scriptUriLocation = "document"
        else:
            self.m_baseUri = expandUri( self.s_UriMap[location] )
            self.m_scriptUriLocation = location
        log.debug( "initialized urihelper with baseUri="+self.m_baseUri + ",m_scriptUriLocation="+self.m_scriptUriLocation )

    def getRootStorageURI( self ):
        return self.m_baseUri

    def getStorageURI( self, scriptURI ):
        return self.scriptURI2StorageUri(scriptURI)

    def getScriptURI( self, storageURI ):
        return self.storageURI2ScriptUri(storageURI)

    def storageURI2ScriptUri( self, storageURI ):
        if not storageURI.startswith( self.m_baseUri ):
            message = "pythonscript: storage uri '" + storageURI + "' not in base uri '" + self.m_baseUri + "'"
            log.debug( message )
            raise RuntimeException( message )

        ret = "vnd.sun.star.script:" + \
              storageURI[len(self.m_baseUri)+1:].replace("/","|") + \
              "?language=" + LANGUAGENAME + "&location=" + self.m_scriptUriLocation
        log.debug( "converting storageURI="+storageURI + " to scriptURI=" + ret )
        return ret

    def scriptURI2StorageUri( self, scriptURI ):
        try:
            myUri = self.m_uriRefFac.parse(scriptURI)
            ret = self.m_baseUri + "/" + myUri.getName().replace( "|", "/" )
            log.debug( "converting scriptURI="+scriptURI + " to storageURI=" + ret )
            return ret
        except UnoException as e:
            log.error( "error during converting scriptURI="+scriptURI + ": " + e.Message)
            raise RuntimeException( "pythonscript:scriptURI2StorageUri: " +e.getMessage(), None )
        except Exception as e:
            log.error( "error during converting scriptURI="+scriptURI + ": " + str(e))
            raise RuntimeException( "pythonscript:scriptURI2StorageUri: " + str(e), None )


class ModuleEntry:
    def __init__( self, lastRead, module ):
        self.lastRead = lastRead
        self.module = module

def hasChanged( oldDate, newDate ):
    return newDate.Year > oldDate.Year or \
           newDate.Month > oldDate.Month or \
           newDate.Day > oldDate.Day or \
           newDate.Hours > oldDate.Hours or \
           newDate.Minutes > oldDate.Minutes or \
           newDate.Seconds > oldDate.Seconds or \
           newDate.HundredthSeconds > oldDate.HundredthSeconds

def ensureSourceState( code ):
    if not code.endswith( "\n" ):
        code = code + "\n"
    code = code.replace( "\r", "" )
    return code


def checkForPythonPathBesideScript( url ):
    if url.startswith( "file:" ):
        path = unohelper.fileUrlToSystemPath( url+"/pythonpath.zip" );
        log.log( LogLevel.DEBUG,  "checking for existence of " + path )
        if 1 == os.access( encfile(path), os.F_OK) and not path in sys.path:
            log.log( LogLevel.DEBUG, "adding " + path + " to sys.path" )
            sys.path.append( path )

        path = unohelper.fileUrlToSystemPath( url+"/pythonpath" );
        log.log( LogLevel.DEBUG,  "checking for existence of " + path )
        if 1 == os.access( encfile(path), os.F_OK) and not path in sys.path:
            log.log( LogLevel.DEBUG, "adding " + path + " to sys.path" )
            sys.path.append( path )


class ScriptContext(unohelper.Base):
    def __init__( self, ctx, doc, inv ):
        self.ctx = ctx
        self.doc = doc
        self.inv = inv

   # XScriptContext
    def getDocument(self):
        if self.doc:
            return self.doc
        return self.getDesktop().getCurrentComponent()

    def getDesktop(self):
        return self.ctx.ServiceManager.createInstanceWithContext(
            "com.sun.star.frame.Desktop", self.ctx )

    def getComponentContext(self):
        return self.ctx

    def getInvocationContext(self):
        return self.inv

#----------------------------------
# Global Module Administration
# does not fit together with script
# engine lifetime management
#----------------------------------
#g_scriptContext = ScriptContext( uno.getComponentContext(), None )
#g_modules = {}
#def getModuleByUrl( url, sfa ):
#    entry =  g_modules.get(url)
#    load = True
#    lastRead = sfa.getDateTimeModified( url )
#    if entry:
#        if hasChanged( entry.lastRead, lastRead ):
#            log.debug("file " + url + " has changed, reloading")
#        else:
#            load = False
#
#    if load:
#        log.debug( "opening >" + url + "<" )
#
#        code = readTextFromStream( sfa.openFileRead( url ) )

        # execute the module
#        entry = ModuleEntry( lastRead, types.ModuleType("ooo_script_framework") )
#        entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = g_scriptContext
#        entry.module.__file__ = url
#        exec code in entry.module.__dict__
#        g_modules[ url ] = entry
#        log.debug( "mapped " + url + " to " + str( entry.module ) )
#    return entry.module

class ProviderContext:
    def __init__( self, storageType, sfa, uriHelper, scriptContext ):
        self.storageType = storageType
        self.sfa = sfa
        self.uriHelper = uriHelper
        self.scriptContext = scriptContext
        self.modules = {}
        self.rootUrl = None
        self.mapPackageName2Path = None

    def getTransientPartFromUrl( self, url ):
        rest = url.replace( self.rootUrl , "",1 ).replace( "/","",1)
        return rest[0:rest.find("/")]

    def getPackageNameFromUrl( self, url ):
        rest = url.replace( self.rootUrl , "",1 ).replace( "/","",1)
        start = rest.find("/") +1
        return rest[start:rest.find("/",start)]


    def removePackageByUrl( self, url ):
        items = list(self.mapPackageName2Path.items())
        for i in items:
            if url in i[1].pathes:
                self.mapPackageName2Path.pop(i[0])
                break

    def addPackageByUrl( self, url ):
        packageName = self.getPackageNameFromUrl( url )
        transientPart = self.getTransientPartFromUrl( url )
        log.debug( "addPackageByUrl : " + packageName + ", " + transientPart + "("+url+")" + ", rootUrl="+self.rootUrl )
        if packageName in self.mapPackageName2Path:
            package = self.mapPackageName2Path[ packageName ]
            package.pathes = package.pathes + (url, )
        else:
            package = Package( (url,), transientPart)
            self.mapPackageName2Path[ packageName ] = package

    def isUrlInPackage( self, url ):
        values = list(self.mapPackageName2Path.values())
        for i in values:
#           print "checking " + url + " in " + str(i.pathes)
            if url in i.pathes:
                return True
#        print "false"
        return False

    def setPackageAttributes( self, mapPackageName2Path, rootUrl ):
        self.mapPackageName2Path = mapPackageName2Path
        self.rootUrl = rootUrl

    def getPersistentUrlFromStorageUrl( self, url ):
        # package name is the second directory
        ret = url
        if self.rootUrl:
            pos = len( self.rootUrl) +1
            ret = url[0:pos]+url[url.find("/",pos)+1:len(url)]
        log.debug( "getPersistentUrlFromStorageUrl " + url +  " -> "+ ret)
        return ret

    def getStorageUrlFromPersistentUrl( self, url):
        ret = url
        if self.rootUrl:
            pos = len(self.rootUrl)+1
            packageName = url[pos:url.find("/",pos+1)]
            package = self.mapPackageName2Path[ packageName ]
            ret = url[0:pos]+ package.transientPathElement + "/" + url[pos:len(url)]
        log.debug( "getStorageUrlFromPersistentUrl " + url + " -> "+ ret)
        return ret

    def getFuncsByUrl( self, url ):
        src = readTextFromStream( self.sfa.openFileRead( url ) )
        checkForPythonPathBesideScript( url[0:url.rfind('/')] )
        src = ensureSourceState( src )

        allFuncs = []
        g_exportedScripts = []

        a = ast.parse(src, url)

        if isinstance(a, ast.Module):
            for node in a.body:
                if isinstance(node, ast.FunctionDef):
                    allFuncs.append(node.name)
                elif isinstance(node, ast.Assign):
                    is_exported = False
                    for subnode in node.targets:
                        if isinstance(subnode, ast.Name) and \
                            subnode.id == "g_exportedScripts":
                            is_exported = True
                            break
                    if is_exported:
                        value_node = node.value
                        if isinstance(value_node, ast.List) or \
                            isinstance(value_node, ast.Tuple):
                            for elt in value_node.elts:
                                if isinstance(elt, ast.Str):
                                    g_exportedScripts.append(elt.s)
                                elif isinstance(elt, ast.Name):
                                    g_exportedScripts.append(elt.id)
                        elif isinstance(value_node, ast.Str):
                            g_exportedScripts.append(value_node.s)
                        elif isinstance(value_node, ast.Name):
                            g_exportedScripts.append(value_node.id)
                        return g_exportedScripts
        return allFuncs

    def getModuleByUrl( self, url ):
        entry =  self.modules.get(url)
        load = True
        lastRead = self.sfa.getDateTimeModified( url )
        if entry:
            if hasChanged( entry.lastRead, lastRead ):
                log.debug( "file " + url + " has changed, reloading" )
            else:
                load = False

        if load:
            log.debug( "opening >" + url + "<" )

            src = readTextFromStream( self.sfa.openFileRead( url ) )
            checkForPythonPathBesideScript( url[0:url.rfind('/')] )
            src = ensureSourceState( src )

            # execute the module
            entry = ModuleEntry( lastRead, types.ModuleType("ooo_script_framework") )
            entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.scriptContext

            code = None
            if url.startswith( "file:" ):
                code = compile( src, encfile(uno.fileUrlToSystemPath( url ) ), "exec" )
            else:
                code = compile( src, url, "exec" )
            exec(code, entry.module.__dict__)
            entry.module.__file__ = url
            self.modules[ url ] = entry
            log.debug( "mapped " + url + " to " + str( entry.module ) )
        return  entry.module

    # Forgets a stale module so a fresh copy can be loaded in the future.
    # This is necessary because getModuleByUrl()'s self.sfa.getDateTimeModified()
    # doesn't always work, eg. for embedded scripts it always returns timestamps
    # with all zeroes, and even if it worked, the smallest granularity for ZIP file
    # timestamps is 2 seconds, which isn't good enough.
    def removeModuleByUrl( self, url ):
        self.modules.pop( url, None )

def createEditorDialog( ctx ):
    smgr = ctx.ServiceManager

    dialogModel = smgr.createInstanceWithContext(
        "com.sun.star.awt.UnoControlDialogModel", ctx)
    dialogModel.PositionX = 105
    dialogModel.PositionY = 117
    dialogModel.Width = 240
    dialogModel.Height = 320
    dialogModel.Closeable = True
    dialogModel.Moveable = True
    dialogModel.Title = "Python Macro Editor"

    runButtonModel = dialogModel.createInstance(
        "com.sun.star.awt.UnoControlButtonModel" )
    runButtonModel.PositionX = 57
    runButtonModel.PositionY = 300
    runButtonModel.Width = 40
    runButtonModel.Height = 14
    runButtonModel.TabIndex = 0
    runButtonModel.Label = "Run"

    saveButtonModel = dialogModel.createInstance(
        "com.sun.star.awt.UnoControlButtonModel" )
    saveButtonModel.PositionX = 100
    saveButtonModel.PositionY = 300
    saveButtonModel.Width = 40
    saveButtonModel.Height = 14
    saveButtonModel.TabIndex = 1
    saveButtonModel.Label = "Save"

    closeButtonModel = dialogModel.createInstance(
        "com.sun.star.awt.UnoControlButtonModel" )
    closeButtonModel.PositionX = 143
    closeButtonModel.PositionY = 300
    closeButtonModel.Width = 40
    closeButtonModel.Height = 14
    closeButtonModel.TabIndex = 2
    closeButtonModel.PushButtonType = 2  # CANCEL
    closeButtonModel.Label = "Close"

    fontDescriptor = FontDescriptor()
    fontDescriptor.Name = "SomeFixedWidthFont"
    fontDescriptor.Pitch = FIXED

    textFieldModel = dialogModel.createInstance(
        "com.sun.star.awt.UnoControlEditModel" )
    textFieldModel.PositionX = 6
    textFieldModel.PositionY = 6
    textFieldModel.Width = 228
    textFieldModel.Height = 288
    textFieldModel.TabIndex = 3
    textFieldModel.HScroll = True
    textFieldModel.VScroll = True
    textFieldModel.MultiLine = True
    textFieldModel.FontDescriptor = fontDescriptor

    dialogModel.insertByName( "RunButton", runButtonModel )
    dialogModel.insertByName( "SaveButton", saveButtonModel )
    dialogModel.insertByName( "CloseButton", closeButtonModel )
    dialogModel.insertByName( "EditorTextField", textFieldModel )

    # create the dialog control and set the model
    controlContainer = smgr.createInstanceWithContext(
        "com.sun.star.awt.UnoControlDialog", ctx);
    controlContainer.setModel(dialogModel);

    # create a peer
    toolkit = smgr.createInstanceWithContext(
        "com.sun.star.awt.ExtToolkit", ctx);

    controlContainer.setVisible(False);
    controlContainer.createPeer(toolkit, None);

    return controlContainer


#--------------------------------------------------
def isScript( candidate ):
    ret = False
    if isinstance( candidate, type(isScript) ):
        ret = True
    return ret

#-------------------------------------------------------
class ScriptBrowseNode( unohelper.Base, XBrowseNode, XPropertySet, XInvocation, XActionListener ):
    def __init__( self, provCtx, parent, fileName, funcName ):
        self.parent = parent
        self.fileName = fileName
        self.funcName = funcName
        self.provCtx = provCtx

    def uri( self ):
        return self.parent.uri()

    def getName( self ):
        return self.funcName

    def getChildNodes(self):
        return ()

    def hasChildNodes(self):
        return False

    def getType( self):
        return SCRIPT

    def getPropertyValue( self, name ):
        ret = None
        try:
            if name == "URI":
                ret = self.provCtx.uriHelper.getScriptURI(
                    self.provCtx.getPersistentUrlFromStorageUrl( self.uri() + "$" + self.funcName ) )
            elif name == "Editable":
                ret = not self.provCtx.sfa.isReadOnly( self.uri() )

            log.debug( "ScriptBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) )
        except Exception as e:
            log.error( "ScriptBrowseNode.getPropertyValue error " + lastException2String())
            raise

        return ret
    def setPropertyValue( self, name, value ):
        log.debug( "ScriptBrowseNode.setPropertyValue called " + name + "=" +str(value ) )
    def getPropertySetInfo( self ):
        log.debug( "ScriptBrowseNode.getPropertySetInfo called "  )
        return None

    def getIntrospection( self ):
        return None

    def invoke( self, name, params, outparamindex, outparams ):
        if name == "Editable":
            ctx = self.provCtx.scriptContext.getComponentContext()

            self.editor = createEditorDialog( ctx )

            code = readTextFromStream(self.provCtx.sfa.openFileRead(self.uri()))
            code = ensureSourceState( code )
            self.editor.getControl("EditorTextField").setText(code)

            self.editor.getControl("RunButton").setActionCommand("Run")
            self.editor.getControl("RunButton").addActionListener(self)
            self.editor.getControl("SaveButton").setActionCommand("Save")
            self.editor.getControl("SaveButton").addActionListener(self)

            self.editor.execute()

        return None, (), ()

    def actionPerformed( self, event ):
        try:
            if event.ActionCommand == "Run":
                code = self.editor.getControl("EditorTextField").getText()
                code = ensureSourceState( code )
                mod = types.ModuleType("ooo_script_framework")
                mod.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.provCtx.scriptContext
                exec(code, mod.__dict__)
                values = mod.__dict__.get( CALLABLE_CONTAINER_NAME , None )
                if not values:
                    values = list(mod.__dict__.values())

                for i in values:
                    if isScript( i ):
                        i()
                        break

            elif event.ActionCommand == "Save":
                toWrite = uno.ByteSequence(
                    self.editor.getControl("EditorTextField").getText().encode("utf-8"))
                log.debug( "Saving Python macro to URI " + self.uri() )
                self.provCtx.sfa.writeFile( self.uri(), BytesInputStream( toWrite.value ) )
                self.provCtx.removeModuleByUrl( self.uri() )
        except Exception as e:
            # TODO: add an error box here !
            log.error( lastException2String() )


    def setValue( self, name, value ):
        return None

    def getValue( self, name ):
        return None

    def hasMethod( self, name ):
        return False

    def hasProperty( self, name ):
        return False


#-------------------------------------------------------
class FileBrowseNode( unohelper.Base, XBrowseNode, XPropertySet, XInvocation, XActionListener ):
    def __init__( self, provCtx, parent, name ):
        self.provCtx = provCtx
        self.parent = parent
        self.name = name
        self.funcnames = None

    def uri( self ):
        return self.parent.rootUrl + "/" + self.name + ".py"

    def getName( self ):
        return self.name

    def getChildNodes(self):
        ret = ()
        try:
            self.funcnames = self.provCtx.getFuncsByUrl( self.uri() )

            scriptNodeList = []
            for i in self.funcnames:
                scriptNodeList.append(
                    ScriptBrowseNode(
                    self.provCtx, self, self.name, i ))
            ret = tuple( scriptNodeList )
        except Exception as e:
            text = lastException2String()
            log.error( "FileBrowseNode.getChildNodes error while evaluating " + self.uri() + ":" + text )
            raise
        return ret

    def hasChildNodes(self):
        try:
            return len(self.getChildNodes()) > 0
        except Exception as e:
            return False

    def getType( self):
        return CONTAINER

    # XPropertySet

    def getPropertyValue( self, name ):
        ret = None
        try:
            if name == "Editable":
                ret = not self.provCtx.sfa.isReadOnly( self.uri() )
            elif name == "Deletable":
                ret = not self.provCtx.sfa.isReadOnly( self.uri() )
            elif name == "Renamable":
                ret = not self.provCtx.sfa.isReadOnly( self.uri() )

            log.debug( "FileBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) )
        except Exception as e:
            log.error( "FileBrowseNode.getPropertyValue error " + lastException2String())
            raise

        return ret

    def setPropertyValue( self, name, value ):
        log.debug( "FileBrowseNode.setPropertyValue called " + name + "=" +str(value ) )

    def getPropertySetInfo( self ):
        log.debug( "FileBrowseNode.getPropertySetInfo called "  )
        return None

    # XInvocation

    def getIntrospection( self ):
        log.debug( "FileBrowseNode.getIntrospection() called" )
        return None

    def invoke( self, name, params, outparamindex, outparams ):
        log.debug("FileBrowseNode.invoke called for " + name + "," + str(params) + "," + str(outparamindex) + "," + str(outparams))
        try:
            if name == "Editable":
                ctx = self.provCtx.scriptContext.getComponentContext()

                self.editor = createEditorDialog( ctx )

                code = readTextFromStream(self.provCtx.sfa.openFileRead(self.uri()))
                code = ensureSourceState( code )
                self.editor.getControl("EditorTextField").setText(code)

                self.editor.getControl("RunButton").setActionCommand("Run")
                self.editor.getControl("RunButton").addActionListener(self)
                self.editor.getControl("SaveButton").setActionCommand("Save")
                self.editor.getControl("SaveButton").addActionListener(self)

                self.editor.execute()
            elif name == "Deletable":
                self.provCtx.sfa.kill( self.uri() )
                return True, (), ()
            elif name == "Renamable":
                if params is None or not params:
                    raise IllegalArgumentException( "invoke with Creatable needs the name in params" )
                newUri = self.parent.rootUrl + "/" + params[0] + ".py"
                self.provCtx.sfa.move( self.uri(), newUri )
                self.name = params[0]
                return self, (), ()
        except Exception as e:
            log.error( "FileBrowseNode.invoke error " + lastException2String() )
            raise
        return None, (), ()

    def setValue( self, name, value ):
        return None

    def getValue( self, name ):
        log.debug( "FileBrowseNode.getValue() called" )
        return None

    def hasMethod( self, name ):
        return False

    def hasProperty( self, name ):
        return False

    # XActionListener

    def actionPerformed( self, event ):
        try:
            if event.ActionCommand == "Run":
                code = self.editor.getControl("EditorTextField").getText()
                code = ensureSourceState( code )
                mod = types.ModuleType("ooo_script_framework")
                mod.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.provCtx.scriptContext
                exec(code, mod.__dict__)
                values = mod.__dict__.get( CALLABLE_CONTAINER_NAME , None )
                if not values:
                    values = list(mod.__dict__.values())

                for i in values:
                    if isScript( i ):
                        i()
                        break

            elif event.ActionCommand == "Save":
                toWrite = uno.ByteSequence(
                    self.editor.getControl("EditorTextField").getText().encode("utf-8"))
                log.debug( "Saving Python macro to URI " + self.uri() )
                self.provCtx.sfa.writeFile( self.uri(), BytesInputStream( toWrite.value ) )
                self.provCtx.removeModuleByUrl( self.uri() )
        except Exception as e:
            # TODO: add an error box here !
            log.error( lastException2String() )


class DirBrowseNode( unohelper.Base, XBrowseNode, XPropertySet, XInvocation ):
    def __init__( self, provCtx, name, rootUrl, depth ):
        self.provCtx = provCtx
        self.name = name
        self.rootUrl = rootUrl
        self.depth = depth
        log.debug( "DirBrowseNode constructor for " + name + "," + rootUrl )

    def getName( self ):
        return self.name

    def getChildNodes( self ):
        try:
            log.debug( "DirBrowseNode.getChildNodes called for " + self.rootUrl )
            contents = self.provCtx.sfa.getFolderContents( self.rootUrl, True )
            browseNodeList = []
            for i in contents:
                if i.endswith( ".py" ):
                    log.debug( "adding filenode " + i )
                    browseNodeList.append(
                        FileBrowseNode( self.provCtx, self, i[i.rfind("/")+1:len(i)-3] ) )
                elif self.provCtx.sfa.isFolder( i ) and not i.endswith("/pythonpath"):
                    log.debug( "adding DirBrowseNode " + i )
                    browseNodeList.append(
                        DirBrowseNode( self.provCtx, i[i.rfind("/")+1:len(i)], i, self.depth + 1 ) )
            return tuple( browseNodeList )
        except Exception as e:
            text = lastException2String()
            log.error( "DirBrowseNode error: " + str(e) + " while evaluating " + self.rootUrl)
            log.error( text)
            return ()

    def hasChildNodes( self ):
        return True

    def getType( self ):
        return CONTAINER

    # XScriptProvider

    def getScript( self, uri ):
        log.debug( "DirBrowseNode getScript " + uri + " invoked" )
        raise IllegalArgumentException( "DirBrowseNode couldn't instantiate script " + uri , self , 0 )

    # XPropertySet

    def getPropertyValue( self, name ):
        ret = None
        try:
            if name == "Creatable":
                ret = True
            elif name == "Deletable":
                ret = self.depth > 0 and not self.provCtx.sfa.isReadOnly( self.rootUrl )
            elif name == "Renamable":
                ret = self.depth > 0 and not self.provCtx.sfa.isReadOnly( self.rootUrl )

            log.debug( "DirBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) )
        except Exception as e:
            log.error( "DirBrowseNode.getPropertyValue error " + lastException2String())
            raise

        return ret

    def setPropertyValue( self, name, value ):
        log.debug( "DirBrowseNode.setPropertyValue called " + name + "=" +str(value ) )

    def getPropertySetInfo( self ):
        log.debug( "DirBrowseNode.getPropertySetInfo called "  )
        return None

    # XInvocation

    def getIntrospection( self ):
        log.debug( "DirBrowseNode.getIntrospection() called" )
        return None

    def invoke( self, name, params, outparamindex, outparams ):
        log.debug("DirBrowseNode.invoke called for " + name + "," + str(params) + "," + str(outparamindex) + "," + str(outparams))
        try:
            if name == "Creatable":
                if params is None or not params:
                    raise IllegalArgumentException( "invoke with Creatable needs the name in params" )
                if self.depth == 0:
                    subFolderUrl = self.rootUrl + "/" + params[0]
                    self.provCtx.sfa.createFolder( subFolderUrl )
                    childNode = DirBrowseNode( self.provCtx, subFolderUrl[subFolderUrl.rfind("/")+1:len(subFolderUrl)], subFolderUrl, self.depth + 1 )
                    return childNode, (), ()
                else:
                    scriptUrl = self.rootUrl + "/" + params[0] + ".py"
                    # Creates an empty file
                    self.provCtx.sfa.writeFile( scriptUrl, EmptyInputStream() )
                    childNode = FileBrowseNode( self.provCtx, self, params[0] )
                    return childNode, (), ()
            elif name == "Deletable":
                self.provCtx.sfa.kill( self.rootUrl )
                return True, (), ()
            elif name == "Renamable":
                if params is None or not params:
                    raise IllegalArgumentException( "invoke with Renamable needs the name in params" )
                newUrl = self.rootUrl[0:self.rootUrl.rfind("/")+1] + params[0]
                self.provCtx.sfa.move( self.rootUrl, newUrl )
                self.rootUrl = newUrl
                self.name = params[0]
                return self, (), ()
        except Exception as e:
            log.error( "DirBrowseNode.invoke error: " + lastException2String())
            raise
        return None, (), ()

    def setValue( self, name, value ):
        return None

    def getValue( self, name ):
        log.debug( "DirBrowseNode.getValue() called" )
        return None

    def hasMethod( self, name ):
        return False

    def hasProperty( self, name ):
        return False


class ManifestHandler( XDocumentHandler, unohelper.Base ):
    def __init__( self, rootUrl ):
        self.rootUrl = rootUrl

    def startDocument( self ):
        self.urlList = []

    def endDocument( self ):
        pass

    def startElement( self , name, attlist):
        if name == "manifest:file-entry":
            if attlist.getValueByName( "manifest:media-type" ) == "application/vnd.sun.star.framework-script":
                self.urlList.append(
                    self.rootUrl + "/" + attlist.getValueByName( "manifest:full-path" ) )

    def endElement( self, name ):
        pass

    def characters ( self, chars ):
        pass

    def ignoreableWhitespace( self, chars ):
        pass

    def setDocumentLocator( self, locator ):
        pass

def isPyFileInPath( sfa, path ):
    ret = False
    contents = sfa.getFolderContents( path, True )
    for i in contents:
        if sfa.isFolder(i):
            ret = isPyFileInPath(sfa,i)
        else:
            if i.endswith(".py"):
                ret = True
        if ret:
            break
    return ret

# extracts META-INF directory from
def getPathesFromPackage( rootUrl, sfa ):
    ret = ()
    try:
        fileUrl = rootUrl + "/META-INF/manifest.xml"
        inputStream = sfa.openFileRead( fileUrl )
        parser = uno.getComponentContext().ServiceManager.createInstance( "com.sun.star.xml.sax.Parser" )
        handler = ManifestHandler( rootUrl )
        parser.setDocumentHandler( handler )
        parser.parseStream( InputSource( inputStream , "", fileUrl, fileUrl ) )
        for i in tuple(handler.urlList):
            if not isPyFileInPath( sfa, i ):
                handler.urlList.remove(i)
        ret = tuple( handler.urlList )
    except UnoException as e:
        text = lastException2String()
        log.debug( "getPathesFromPackage " + fileUrl + " Exception: " +text )
        pass
    return ret


class Package:
    def __init__( self, pathes, transientPathElement ):
        self.pathes = pathes
        self.transientPathElement = transientPathElement

class DummyInteractionHandler( unohelper.Base, XInteractionHandler ):
    def __init__( self ):
        pass
    def handle( self, event):
        log.debug( "pythonscript: DummyInteractionHandler.handle " + str( event ) )

class DummyProgressHandler( unohelper.Base, XProgressHandler ):
    def __init__( self ):
        pass

    def push( self,status ):
        log.debug( "pythonscript: DummyProgressHandler.push " + str( status ) )
    def update( self,status ):
        log.debug( "pythonscript: DummyProgressHandler.update " + str( status ) )
    def pop( self ):
        log.debug( "pythonscript: DummyProgressHandler.push " + str( event ) )

class CommandEnvironment(unohelper.Base, XCommandEnvironment):
    def __init__( self ):
        self.progressHandler = DummyProgressHandler()
        self.interactionHandler = DummyInteractionHandler()
    def getInteractionHandler( self ):
        return self.interactionHandler
    def getProgressHandler( self ):
        return self.progressHandler

#maybe useful for debugging purposes
#class ModifyListener( unohelper.Base, XModifyListener ):
#    def __init__( self ):
#        pass
#    def modified( self, event ):
#        log.debug( "pythonscript: ModifyListener.modified " + str( event ) )
#    def disposing( self, event ):
#        log.debug( "pythonscript: ModifyListener.disposing " + str( event ) )

def getModelFromDocUrl(ctx, url):
    """Get document model from document url."""
    doc = None
    args = ("Local", "Office")
    ucb = ctx.getServiceManager().createInstanceWithArgumentsAndContext(
        "com.sun.star.ucb.UniversalContentBroker", args, ctx)
    identifier = ucb.createContentIdentifier(url)
    content = ucb.queryContent(identifier)
    p = Property()
    p.Name = "DocumentModel"
    p.Handle = -1

    c = Command()
    c.Handle = -1
    c.Name = "getPropertyValues"
    c.Argument = uno.Any("[]com.sun.star.beans.Property", (p,))

    env = CommandEnvironment()
    try:
        ret = content.execute(c, 0, env)
        doc = ret.getObject(1, None)
    except Exception as e:
        log.isErrorLevel() and log.error("getModelFromDocUrl: %s" % url)
    return doc

def mapStorageType2PackageContext( storageType ):
    ret = storageType
    if( storageType == "share:uno_packages" ):
        ret = "shared"
    if( storageType == "user:uno_packages" ):
        ret = "user"
    return ret

def getPackageName2PathMap( sfa, storageType ):
    ret = {}
    packageManagerFactory = uno.getComponentContext().getValueByName(
        "/singletons/com.sun.star.deployment.thePackageManagerFactory" )
    packageManager = packageManagerFactory.getPackageManager(
        mapStorageType2PackageContext(storageType))
#    packageManager.addModifyListener( ModifyListener() )
    log.debug( "pythonscript: getPackageName2PathMap start getDeployedPackages" )
    packages = packageManager.getDeployedPackages(
        packageManager.createAbortChannel(), CommandEnvironment( ) )
    log.debug( "pythonscript: getPackageName2PathMap end getDeployedPackages (" + str(len(packages))+")" )

    for i in packages:
        log.debug( "inspecting package " + i.Name + "("+i.Identifier.Value+")" )
        transientPathElement = penultimateElement( i.URL )
        j = expandUri( i.URL )
        pathes = getPathesFromPackage( j, sfa )
        if len( pathes ) > 0:
            # map package name to url, we need this later
            log.isErrorLevel() and log.error( "adding Package " + transientPathElement + " " + str( pathes ) )
            ret[ lastElement( j ) ] = Package( pathes, transientPathElement )
    return ret

def penultimateElement( aStr ):
    lastSlash = aStr.rindex("/")
    penultimateSlash = aStr.rindex("/",0,lastSlash-1)
    return  aStr[ penultimateSlash+1:lastSlash ]

def lastElement( aStr):
    return aStr[ aStr.rfind( "/" )+1:len(aStr)]

class PackageBrowseNode( unohelper.Base, XBrowseNode, XPropertySet, XInvocation ):
    def __init__( self, provCtx, name, rootUrl ):
        self.provCtx = provCtx
        self.name = name
        self.rootUrl = rootUrl

    def getName( self ):
        return self.name

    def getChildNodes( self ):
        items = list(self.provCtx.mapPackageName2Path.items())
        browseNodeList = []
        for i in items:
            if len( i[1].pathes ) == 1:
                browseNodeList.append(
                    DirBrowseNode( self.provCtx, i[0], i[1].pathes[0], 0 ))
            else:
                for j in i[1].pathes:
                    browseNodeList.append(
                        DirBrowseNode( self.provCtx, i[0]+"."+lastElement(j), j, 0 ) )
        return tuple( browseNodeList )

    def hasChildNodes( self ):
        return len( self.mapPackageName2Path ) > 0

    def getType( self ):
        return CONTAINER

    def getScript( self, uri ):
        log.debug( "DirBrowseNode getScript " + uri + " invoked" )
        raise IllegalArgumentException( "PackageBrowseNode couldn't instantiate script " + uri , self , 0 )

    # XPropertySet

    def getPropertyValue( self, name ):
        ret = None
        log.debug( "PackageBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) )
        return ret

    def setPropertyValue( self, name, value ):
        log.debug( "PackageBrowseNode.setPropertyValue " + name + "=" +str( value ) )

    def getPropertySetInfo( self ):
        log.debug( "PackageBrowseNode.getPropertySetInfo called" )
        return None

    # XInvocation

    def getIntrospection( self ):
        log.debug( "PackageBrowseNode.getIntrospection() called" )
        return None

    def invoke( self, name, params, outparamindex, outparams ):
        log.debug( "PackageBrowseNode.invoke called for " + name + "," + str( params ) + "," + str( outparamindex ) + "," + str( outparams ) )
        return None, (), ()

    def setValue( self, name, value ):
        log.debug( "PackageBrowseNode.setValue" )
        return None

    def getValue( self, name ):
        log.debug( "PackageBrowseNode.getValue" )
        return None

    def hasMethod( self, name ):
        log.debug( "PackageBrowseNode.hasMethod" )
        return False

    def hasProperty( self, name ):
        log.debug( "PackageBrowseNode.hasProperty" )
        return False



class PythonScript( unohelper.Base, XScript ):
    def __init__( self, func, mod ):
        self.func = func
        self.mod = mod
    def invoke(self, args, out, outindex ):
        log.debug( "PythonScript.invoke " + str( args ) )
        try:
            ret = self.func( *args )
        except UnoException as e:
            # UNO Exception continue to fly ...
            text = lastException2String()
            complete = "Error during invoking function " + \
                str(self.func.__name__) + " in module " + \
                self.mod.__file__ + " (" + text + ")"
            log.debug( complete )
            # some people may beat me up for modifying the exception text,
            # but otherwise office just shows
            # the type name and message text with no more information,
            # this is really bad for most users.
            e.Message = e.Message + " (" + complete + ")"
            raise
        except Exception as e:
            # General python exception are converted to uno RuntimeException
            text = lastException2String()
            complete = "Error during invoking function " + \
                str(self.func.__name__) + " in module " + \
                self.mod.__file__ + " (" + text + ")"
            log.debug( complete )
            raise RuntimeException( complete , self )
        log.debug( "PythonScript.invoke ret = " + str( ret ) )
        return ret, (), ()

def expandUri(  uri ):
    if uri.startswith( "vnd.sun.star.expand:" ):
        uri = uri.replace( "vnd.sun.star.expand:", "",1)
        uri = uno.getComponentContext().getByName(
                    "/singletons/com.sun.star.util.theMacroExpander" ).expandMacros( uri )
    if uri.startswith( "file:" ):
        uri = uno.absolutize("",uri)   # necessary to get rid of .. in uri
    return uri

#--------------------------------------------------------------
class PythonScriptProvider( unohelper.Base, XBrowseNode, XScriptProvider, XNameContainer, XPropertySet, XInvocation):
    def __init__( self, ctx, *args ):
        if log.isDebugLevel():
            mystr = ""
            for i in args:
                if len(mystr) > 0:
                    mystr = mystr +","
                mystr = mystr + str(i)
            log.debug( "Entering PythonScriptProvider.ctor with args " + mystr )

        doc = None
        inv = None
        storageType = ""

        if isinstance(args[0],unicode ):
            storageType = args[0]
            if storageType.startswith( "vnd.sun.star.tdoc" ):
                doc = getModelFromDocUrl(ctx, storageType)
        else:
            inv = args[0]
            try:
                doc = inv.ScriptContainer
                content = ctx.getServiceManager().createInstanceWithContext(
                    "com.sun.star.frame.TransientDocumentsDocumentContentFactory",
                    ctx).createDocumentContent(doc)
                storageType = content.getIdentifier().getContentIdentifier()
            except Exception as e:
                text = lastException2String()
                log.error( text )

        isPackage = storageType.endswith( ":uno_packages" )

        try:
#            urlHelper = ctx.ServiceManager.createInstanceWithArgumentsAndContext(
#                "com.sun.star.script.provider.ScriptURIHelper", (LANGUAGENAME, storageType), ctx)
            urlHelper = MyUriHelper( ctx, storageType )
            log.debug( "got urlHelper " + str( urlHelper ) )

            rootUrl = expandUri( urlHelper.getRootStorageURI() )
            log.debug( storageType + " transformed to " + rootUrl )

            ucbService = "com.sun.star.ucb.SimpleFileAccess"
            sfa = ctx.ServiceManager.createInstanceWithContext( ucbService, ctx )
            if not sfa:
                log.debug("PythonScriptProvider couldn't instantiate " +ucbService)
                raise RuntimeException(
                    "PythonScriptProvider couldn't instantiate " +ucbService, self)
            self.provCtx = ProviderContext(
                storageType, sfa, urlHelper, ScriptContext( uno.getComponentContext(), doc, inv ) )
            if isPackage:
                mapPackageName2Path = getPackageName2PathMap( sfa, storageType )
                self.provCtx.setPackageAttributes( mapPackageName2Path , rootUrl )
                self.dirBrowseNode = PackageBrowseNode( self.provCtx, LANGUAGENAME, rootUrl )
            else:
                self.dirBrowseNode = DirBrowseNode( self.provCtx, LANGUAGENAME, rootUrl, 0 )

        except Exception as e:
            text = lastException2String()
            log.debug( "PythonScriptProvider could not be instantiated because of : " + text )
            raise e

    def getName( self ):
        return self.dirBrowseNode.getName()

    def getChildNodes( self ):
        return self.dirBrowseNode.getChildNodes()

    def hasChildNodes( self ):
        return self.dirBrowseNode.hasChildNodes()

    def getType( self ):
        return self.dirBrowseNode.getType()

    def getScript( self, scriptUri ):
        try:
            log.debug( "DirBrowseNode getScript " + scriptUri + " invoked")

            storageUri = self.provCtx.getStorageUrlFromPersistentUrl(
                self.provCtx.uriHelper.getStorageURI(scriptUri) );
            log.debug( "getScript: storageUri = " + storageUri)
            fileUri = storageUri[0:storageUri.find( "$" )]
            funcName = storageUri[storageUri.find( "$" )+1:len(storageUri)]

            mod = self.provCtx.getModuleByUrl( fileUri )
            log.debug( " got mod " + str(mod) )

            func = mod.__dict__[ funcName ]

            log.debug( "got func " + str( func ) )
            return PythonScript( func, mod )
        except Exception as e:
            text = lastException2String()
            log.error( text )
            raise ScriptFrameworkErrorException( text, self, scriptUri, LANGUAGENAME, 0 )

    # XPropertySet

    def getPropertyValue( self, name ):
        return self.dirBrowseNode.getPropertyValue( name )

    def setPropertyValue( self, name, value ):
        return self.dirBrowseNode.setPropertyValue( name, value )

    def getPropertySetInfo( self ):
        return self.dirBrowseNode.getPropertySetInfo()

    # XInvocation

    def getIntrospection( self ):
        return self.dirBrowseNode.getIntrospection()

    def invoke( self, name, params, outparamindex, outparams ):
        return self.dirBrowseNode.invoke( name, params, outparamindex, outparams)

    def setValue( self, name, value ):
        return self.dirBrowseNode.setValue( name, value )

    def getValue( self, name ):
        return self.dirBrowseNode.getValue( name )

    def hasMethod( self, name ):
        return self.dirBrowseNode.hasMethod( name )

    def hasProperty( self, name ):
        return self.dirBrowseNode.hasProperty( name )

    # XServiceInfo
    def getSupportedServices( self ):
        return g_ImplementationHelper.getSupportedServices(g_implName)

    def supportsService( self, ServiceName ):
        return g_ImplementationHelper.supportsService( g_implName, ServiceName )

    def getImplementationName(self):
        return g_implName

    def getByName( self, name ):
        log.debug( "getByName called" + str( name ))
        return None


    def getElementNames( self ):
        log.debug( "getElementNames called")
        return ()

    def hasByName( self, name ):
        try:
            log.debug( "hasByName called " + str( name ))
            uri = expandUri(name)
            ret = self.provCtx.isUrlInPackage( uri )
            log.debug( "hasByName " + uri + " " +str( ret ) )
            return ret
        except Exception as e:
            text = lastException2String()
            log.debug( "Error in hasByName:" +  text )
            return False

    def removeByName( self, name ):
        log.debug( "removeByName called" + str( name ))
        uri = expandUri( name )
        if self.provCtx.isUrlInPackage( uri ):
            self.provCtx.removePackageByUrl( uri )
        else:
            log.debug( "removeByName unknown uri " + str( name ) + ", ignoring" )
            raise NoSuchElementException( uri + "is not in package" , self )
        log.debug( "removeByName called" + str( uri ) + " successful" )

    def insertByName( self, name, value ):
        log.debug( "insertByName called " + str( name ) + " " + str( value ))
        uri = expandUri( name )
        if isPyFileInPath( self.provCtx.sfa, uri ):
            self.provCtx.addPackageByUrl( uri )
        else:
            # package is no python package ...
            log.debug( "insertByName: no python files in " + str( uri ) + ", ignoring" )
            raise IllegalArgumentException( uri + " does not contain .py files", self, 1 )
        log.debug( "insertByName called " + str( uri ) + " successful" )

    def replaceByName( self, name, value ):
        log.debug( "replaceByName called " + str( name ) + " " + str( value ))
        removeByName( name )
        insertByName( name )
        log.debug( "replaceByName called" + str( uri ) + " successful" )

    def getElementType( self ):
        log.debug( "getElementType called" )
        return uno.getTypeByName( "void" )

    def hasElements( self ):
        log.debug( "hasElements got called")
        return False

g_ImplementationHelper.addImplementation( \
        PythonScriptProvider,g_implName, \
    ("com.sun.star.script.provider.LanguageScriptProvider",
     "com.sun.star.script.provider.ScriptProviderFor"+ LANGUAGENAME,),)


log.debug( "pythonscript finished initializing" )
