19f22d7c2SAndrew Rist# *************************************************************
29f22d7c2SAndrew Rist#
39f22d7c2SAndrew Rist#  Licensed to the Apache Software Foundation (ASF) under one
49f22d7c2SAndrew Rist#  or more contributor license agreements.  See the NOTICE file
59f22d7c2SAndrew Rist#  distributed with this work for additional information
69f22d7c2SAndrew Rist#  regarding copyright ownership.  The ASF licenses this file
79f22d7c2SAndrew Rist#  to you under the Apache License, Version 2.0 (the
89f22d7c2SAndrew Rist#  "License"); you may not use this file except in compliance
99f22d7c2SAndrew Rist#  with the License.  You may obtain a copy of the License at
109f22d7c2SAndrew Rist#
119f22d7c2SAndrew Rist#    http://www.apache.org/licenses/LICENSE-2.0
129f22d7c2SAndrew Rist#
139f22d7c2SAndrew Rist#  Unless required by applicable law or agreed to in writing,
149f22d7c2SAndrew Rist#  software distributed under the License is distributed on an
159f22d7c2SAndrew Rist#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
169f22d7c2SAndrew Rist#  KIND, either express or implied.  See the License for the
179f22d7c2SAndrew Rist#  specific language governing permissions and limitations
189f22d7c2SAndrew Rist#  under the License.
199f22d7c2SAndrew Rist#
209f22d7c2SAndrew Rist# *************************************************************
219f22d7c2SAndrew Rist
22cdf0e10cSrcweir# XScript implementation for python
23cdf0e10cSrcweirimport uno
24cdf0e10cSrcweirimport unohelper
25cdf0e10cSrcweirimport sys
26cdf0e10cSrcweirimport os
27cdf0e10cSrcweirimport imp
28cdf0e10cSrcweirimport time
2913cfd8dfSPedro Giffuniimport ast
30cdf0e10cSrcweir
3115745147SPedro Giffunitry:
3215745147SPedro Giffuni    unicode
3315745147SPedro Giffuniexcept NameError:
3415745147SPedro Giffuni    unicode = str
3515745147SPedro Giffuni
36cdf0e10cSrcweirclass LogLevel:
37*b5f289e3SHerbert Dürr    NONE = 0   # production level
38*b5f289e3SHerbert Dürr    ERROR = 1  # for script developers
39*b5f289e3SHerbert Dürr    DEBUG = 2  # for script framework developers
40*b5f289e3SHerbert Dürr
41*b5f289e3SHerbert DürrPYSCRIPT_LOG_ENV = "PYSCRIPT_LOG_LEVEL"
42*b5f289e3SHerbert DürrPYSCRIPT_LOG_STDOUT_ENV = "PYSCRIPT_LOG_STDOUT"
43cdf0e10cSrcweir
44cdf0e10cSrcweir# Configuration ----------------------------------------------------
45*b5f289e3SHerbert DürrLogLevel.use = LogLevel.NONE
46*b5f289e3SHerbert Dürrif os.environ.get(PYSCRIPT_LOG_ENV) == "ERROR":
47*b5f289e3SHerbert Dürr    LogLevel.use = LogLevel.ERROR
48*b5f289e3SHerbert Dürrelif os.environ.get(PYSCRIPT_LOG_ENV) == "DEBUG":
49*b5f289e3SHerbert Dürr    LogLevel.use = LogLevel.DEBUG
50*b5f289e3SHerbert Dürr
51*b5f289e3SHerbert Dürr# True, writes to stdout (difficult on windows)
52*b5f289e3SHerbert Dürr# False, writes to user/Scripts/python/log.txt
53*b5f289e3SHerbert DürrLOG_STDOUT = os.environ.get(PYSCRIPT_LOG_STDOUT_ENV, "1") != "0"
54*b5f289e3SHerbert Dürr
55cdf0e10cSrcweirENABLE_EDIT_DIALOG=False                    # offers a minimal editor for editing.
56cdf0e10cSrcweir#-------------------------------------------------------------------
57cdf0e10cSrcweir
58cdf0e10cSrcweirdef encfile(uni):
59cdf0e10cSrcweir    return uni.encode( sys.getfilesystemencoding())
60cdf0e10cSrcweir
61cdf0e10cSrcweirdef lastException2String():
62cdf0e10cSrcweir    (excType,excInstance,excTraceback) = sys.exc_info()
63cdf0e10cSrcweir    ret = str(excType) + ": "+str(excInstance) + "\n" + \
64cdf0e10cSrcweir          uno._uno_extract_printable_stacktrace( excTraceback )
65cdf0e10cSrcweir    return ret
66cdf0e10cSrcweir
67cdf0e10cSrcweirdef logLevel2String( level ):
68cdf0e10cSrcweir    ret = " NONE"
69cdf0e10cSrcweir    if level == LogLevel.ERROR:
70cdf0e10cSrcweir        ret = "ERROR"
71cdf0e10cSrcweir    elif level >= LogLevel.DEBUG:
72cdf0e10cSrcweir        ret = "DEBUG"
73cdf0e10cSrcweir    return ret
74cdf0e10cSrcweir
75cdf0e10cSrcweirdef getLogTarget():
76cdf0e10cSrcweir    ret = sys.stdout
77cdf0e10cSrcweir    if not LOG_STDOUT:
78cdf0e10cSrcweir        try:
79cdf0e10cSrcweir            pathSubst = uno.getComponentContext().ServiceManager.createInstance(
80cdf0e10cSrcweir                "com.sun.star.util.PathSubstitution" )
81cdf0e10cSrcweir            userInstallation =  pathSubst.getSubstituteVariableValue( "user" )
82cdf0e10cSrcweir            if len( userInstallation ) > 0:
83cdf0e10cSrcweir                systemPath = uno.fileUrlToSystemPath( userInstallation + "/Scripts/python/log.txt" )
84cdf0e10cSrcweir                ret = file( systemPath , "a" )
8515745147SPedro Giffuni        except Exception as e:
8615745147SPedro Giffuni            print("Exception during creation of pythonscript logfile: "+ lastException2String() + "\n, delagating log to stdout\n")
87cdf0e10cSrcweir    return ret
8813cfd8dfSPedro Giffuni
89cdf0e10cSrcweirclass Logger(LogLevel):
90cdf0e10cSrcweir    def __init__(self , target ):
91cdf0e10cSrcweir        self.target = target
92cdf0e10cSrcweir
93cdf0e10cSrcweir    def isDebugLevel( self ):
94cdf0e10cSrcweir        return self.use >= self.DEBUG
9513cfd8dfSPedro Giffuni
96cdf0e10cSrcweir    def debug( self, msg ):
97cdf0e10cSrcweir        if self.isDebugLevel():
98cdf0e10cSrcweir            self.log( self.DEBUG, msg )
9913cfd8dfSPedro Giffuni
100cdf0e10cSrcweir    def isErrorLevel( self ):
101cdf0e10cSrcweir        return self.use >= self.ERROR
102cdf0e10cSrcweir
103cdf0e10cSrcweir    def error( self, msg ):
104cdf0e10cSrcweir        if self.isErrorLevel():
105cdf0e10cSrcweir            self.log( self.ERROR, msg )
106cdf0e10cSrcweir
107cdf0e10cSrcweir    def log( self, level, msg ):
108cdf0e10cSrcweir        if self.use >= level:
109cdf0e10cSrcweir            try:
110cdf0e10cSrcweir                self.target.write(
111cdf0e10cSrcweir                    time.asctime() +
112cdf0e10cSrcweir                    " [" +
113cdf0e10cSrcweir                    logLevel2String( level ) +
114cdf0e10cSrcweir                    "] " +
115cdf0e10cSrcweir                    encfile(msg) +
116cdf0e10cSrcweir                    "\n" )
117cdf0e10cSrcweir                self.target.flush()
11815745147SPedro Giffuni            except Exception as e:
11915745147SPedro Giffuni                print("Error during writing to stdout: " +lastException2String() + "\n")
120cdf0e10cSrcweir
121cdf0e10cSrcweirlog = Logger( getLogTarget() )
122cdf0e10cSrcweir
123cdf0e10cSrcweirlog.debug( "pythonscript loading" )
124cdf0e10cSrcweir
125cdf0e10cSrcweir#from com.sun.star.lang import typeOfXServiceInfo, typeOfXTypeProvider
126cdf0e10cSrcweirfrom com.sun.star.uno import RuntimeException
127cdf0e10cSrcweirfrom com.sun.star.lang import XServiceInfo
128cdf0e10cSrcweirfrom com.sun.star.io import IOException
12961c9e2f8SAriel Constenla-Hailefrom com.sun.star.ucb import CommandAbortedException, XCommandEnvironment, XProgressHandler, Command
130cdf0e10cSrcweirfrom com.sun.star.task import XInteractionHandler
13161c9e2f8SAriel Constenla-Hailefrom com.sun.star.beans import XPropertySet, Property
132cdf0e10cSrcweirfrom com.sun.star.container import XNameContainer
133cdf0e10cSrcweirfrom com.sun.star.xml.sax import XDocumentHandler, InputSource
134cdf0e10cSrcweirfrom com.sun.star.uno import Exception as UnoException
135cdf0e10cSrcweirfrom com.sun.star.script import XInvocation
136cdf0e10cSrcweirfrom com.sun.star.awt import XActionListener
137cdf0e10cSrcweir
138cdf0e10cSrcweirfrom com.sun.star.script.provider import XScriptProvider, XScript, XScriptContext, ScriptFrameworkErrorException
139cdf0e10cSrcweirfrom com.sun.star.script.browse import XBrowseNode
140cdf0e10cSrcweirfrom com.sun.star.script.browse.BrowseNodeTypes import SCRIPT, CONTAINER, ROOT
141cdf0e10cSrcweirfrom com.sun.star.util import XModifyListener
142cdf0e10cSrcweir
143cdf0e10cSrcweirLANGUAGENAME = "Python"
144cdf0e10cSrcweirGLOBAL_SCRIPTCONTEXT_NAME = "XSCRIPTCONTEXT"
145cdf0e10cSrcweirCALLABLE_CONTAINER_NAME =  "g_exportedScripts"
146cdf0e10cSrcweir
147cdf0e10cSrcweir# pythonloader looks for a static g_ImplementationHelper variable
148cdf0e10cSrcweirg_ImplementationHelper = unohelper.ImplementationHelper()
149cdf0e10cSrcweirg_implName = "org.openoffice.pyuno.LanguageScriptProviderFor"+LANGUAGENAME
150cdf0e10cSrcweir
151cdf0e10cSrcweir
152cdf0e10cSrcweir
153cdf0e10cSrcweirBLOCK_SIZE = 65536
154cdf0e10cSrcweirdef readTextFromStream( inputStream ):
155cdf0e10cSrcweir    # read the file
156cdf0e10cSrcweir    code = uno.ByteSequence( "" )
157cdf0e10cSrcweir    while True:
158cdf0e10cSrcweir        read,out = inputStream.readBytes( None , BLOCK_SIZE )
159cdf0e10cSrcweir        code = code + out
160cdf0e10cSrcweir        if read < BLOCK_SIZE:
16113cfd8dfSPedro Giffuni            break
162cdf0e10cSrcweir    return code.value
16313cfd8dfSPedro Giffuni
164cdf0e10cSrcweirdef toIniName( str ):
165cdf0e10cSrcweir    # TODO: what is the official way to get to know whether i am on the windows platform ?
166cdf0e10cSrcweir    if( hasattr(sys , "dllhandle") ):
167cdf0e10cSrcweir        return str + ".ini"
168cdf0e10cSrcweir    return str + "rc"
169cdf0e10cSrcweir
170cdf0e10cSrcweir
171cdf0e10cSrcweir""" definition: storageURI is the system dependent, absolute file url, where the script is stored on disk
172cdf0e10cSrcweir                scriptURI is the system independent uri
173cdf0e10cSrcweir"""
174cdf0e10cSrcweirclass MyUriHelper:
175cdf0e10cSrcweir
176cdf0e10cSrcweir    def __init__( self, ctx, location ):
177cdf0e10cSrcweir        self.s_UriMap = \
178910823aeSJürgen Schmidt        { "share" : "vnd.sun.star.expand:${$OOO_BASE_DIR/program/" +  toIniName( "bootstrap") + "::BaseInstallation}/share/Scripts/python" , \
179cdf0e10cSrcweir          "share:uno_packages" : "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE/uno_packages", \
180910823aeSJürgen Schmidt          "user" : "vnd.sun.star.expand:${$OOO_BASE_DIR/program/" + toIniName( "bootstrap") + "::UserInstallation}/user/Scripts/python" , \
18113cfd8dfSPedro Giffuni          "user:uno_packages" : "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/uno_packages" }
182cdf0e10cSrcweir        self.m_uriRefFac = ctx.ServiceManager.createInstanceWithContext("com.sun.star.uri.UriReferenceFactory",ctx)
183cdf0e10cSrcweir        if location.startswith( "vnd.sun.star.tdoc" ):
184cdf0e10cSrcweir            self.m_baseUri = location + "/Scripts/python"
185cdf0e10cSrcweir            self.m_scriptUriLocation = "document"
186cdf0e10cSrcweir        else:
187cdf0e10cSrcweir            self.m_baseUri = expandUri( self.s_UriMap[location] )
188cdf0e10cSrcweir            self.m_scriptUriLocation = location
189735dd73bSPedro Giffuni        log.debug( "initialized urihelper with baseUri="+self.m_baseUri + ",m_scriptUriLocation="+self.m_scriptUriLocation )
19013cfd8dfSPedro Giffuni
191cdf0e10cSrcweir    def getRootStorageURI( self ):
192cdf0e10cSrcweir        return self.m_baseUri
19313cfd8dfSPedro Giffuni
194cdf0e10cSrcweir    def getStorageURI( self, scriptURI ):
195cdf0e10cSrcweir        return self.scriptURI2StorageUri(scriptURI)
196cdf0e10cSrcweir
197cdf0e10cSrcweir    def getScriptURI( self, storageURI ):
198cdf0e10cSrcweir        return self.storageURI2ScriptUri(storageURI)
199cdf0e10cSrcweir
200cdf0e10cSrcweir    def storageURI2ScriptUri( self, storageURI ):
201cdf0e10cSrcweir        if not storageURI.startswith( self.m_baseUri ):
202cdf0e10cSrcweir            message = "pythonscript: storage uri '" + storageURI + "' not in base uri '" + self.m_baseUri + "'"
203735dd73bSPedro Giffuni            log.debug( message )
204cdf0e10cSrcweir            raise RuntimeException( message )
205cdf0e10cSrcweir
206cdf0e10cSrcweir        ret = "vnd.sun.star.script:" + \
207cdf0e10cSrcweir              storageURI[len(self.m_baseUri)+1:].replace("/","|") + \
208cdf0e10cSrcweir              "?language=" + LANGUAGENAME + "&location=" + self.m_scriptUriLocation
209735dd73bSPedro Giffuni        log.debug( "converting storageURI="+storageURI + " to scriptURI=" + ret )
210cdf0e10cSrcweir        return ret
21113cfd8dfSPedro Giffuni
212cdf0e10cSrcweir    def scriptURI2StorageUri( self, scriptURI ):
213cdf0e10cSrcweir        try:
214cdf0e10cSrcweir            myUri = self.m_uriRefFac.parse(scriptURI)
215cdf0e10cSrcweir            ret = self.m_baseUri + "/" + myUri.getName().replace( "|", "/" )
216735dd73bSPedro Giffuni            log.debug( "converting scriptURI="+scriptURI + " to storageURI=" + ret )
217cdf0e10cSrcweir            return ret
21815745147SPedro Giffuni        except UnoException as e:
219cdf0e10cSrcweir            log.error( "error during converting scriptURI="+scriptURI + ": " + e.Message)
220cdf0e10cSrcweir            raise RuntimeException( "pythonscript:scriptURI2StorageUri: " +e.getMessage(), None )
22115745147SPedro Giffuni        except Exception as e:
222cdf0e10cSrcweir            log.error( "error during converting scriptURI="+scriptURI + ": " + str(e))
223cdf0e10cSrcweir            raise RuntimeException( "pythonscript:scriptURI2StorageUri: " + str(e), None )
22413cfd8dfSPedro Giffuni
225cdf0e10cSrcweir
226cdf0e10cSrcweirclass ModuleEntry:
227cdf0e10cSrcweir    def __init__( self, lastRead, module ):
228cdf0e10cSrcweir        self.lastRead = lastRead
229cdf0e10cSrcweir        self.module = module
230cdf0e10cSrcweir
231cdf0e10cSrcweirdef hasChanged( oldDate, newDate ):
232cdf0e10cSrcweir    return newDate.Year > oldDate.Year or \
233cdf0e10cSrcweir           newDate.Month > oldDate.Month or \
234cdf0e10cSrcweir           newDate.Day > oldDate.Day or \
235cdf0e10cSrcweir           newDate.Hours > oldDate.Hours or \
236cdf0e10cSrcweir           newDate.Minutes > oldDate.Minutes or \
237cdf0e10cSrcweir           newDate.Seconds > oldDate.Seconds or \
238cdf0e10cSrcweir           newDate.HundredthSeconds > oldDate.HundredthSeconds
239cdf0e10cSrcweir
240cdf0e10cSrcweirdef ensureSourceState( code ):
241cdf0e10cSrcweir    if not code.endswith( "\n" ):
242cdf0e10cSrcweir        code = code + "\n"
243cdf0e10cSrcweir    code = code.replace( "\r", "" )
244cdf0e10cSrcweir    return code
245cdf0e10cSrcweir
246cdf0e10cSrcweir
247cdf0e10cSrcweirdef checkForPythonPathBesideScript( url ):
248cdf0e10cSrcweir    if url.startswith( "file:" ):
249cdf0e10cSrcweir        path = unohelper.fileUrlToSystemPath( url+"/pythonpath.zip" );
250cdf0e10cSrcweir        log.log( LogLevel.DEBUG,  "checking for existence of " + path )
251cdf0e10cSrcweir        if 1 == os.access( encfile(path), os.F_OK) and not path in sys.path:
252cdf0e10cSrcweir            log.log( LogLevel.DEBUG, "adding " + path + " to sys.path" )
253cdf0e10cSrcweir            sys.path.append( path )
254cdf0e10cSrcweir
255cdf0e10cSrcweir        path = unohelper.fileUrlToSystemPath( url+"/pythonpath" );
256cdf0e10cSrcweir        log.log( LogLevel.DEBUG,  "checking for existence of " + path )
257cdf0e10cSrcweir        if 1 == os.access( encfile(path), os.F_OK) and not path in sys.path:
258cdf0e10cSrcweir            log.log( LogLevel.DEBUG, "adding " + path + " to sys.path" )
259cdf0e10cSrcweir            sys.path.append( path )
26013cfd8dfSPedro Giffuni
26113cfd8dfSPedro Giffuni
262cdf0e10cSrcweirclass ScriptContext(unohelper.Base):
26361c9e2f8SAriel Constenla-Haile    def __init__( self, ctx, doc, inv ):
264cdf0e10cSrcweir        self.ctx = ctx
265cdf0e10cSrcweir        self.doc = doc
26661c9e2f8SAriel Constenla-Haile        self.inv = inv
26713cfd8dfSPedro Giffuni
268cdf0e10cSrcweir   # XScriptContext
269cdf0e10cSrcweir    def getDocument(self):
27061c9e2f8SAriel Constenla-Haile        if self.doc:
27161c9e2f8SAriel Constenla-Haile            return self.doc
272cdf0e10cSrcweir        return self.getDesktop().getCurrentComponent()
273cdf0e10cSrcweir
274cdf0e10cSrcweir    def getDesktop(self):
275cdf0e10cSrcweir        return self.ctx.ServiceManager.createInstanceWithContext(
276cdf0e10cSrcweir            "com.sun.star.frame.Desktop", self.ctx )
277cdf0e10cSrcweir
278cdf0e10cSrcweir    def getComponentContext(self):
279cdf0e10cSrcweir        return self.ctx
280cdf0e10cSrcweir
28161c9e2f8SAriel Constenla-Haile    def getInvocationContext(self):
28261c9e2f8SAriel Constenla-Haile        return self.inv
28361c9e2f8SAriel Constenla-Haile
284cdf0e10cSrcweir#----------------------------------
285cdf0e10cSrcweir# Global Module Administration
286cdf0e10cSrcweir# does not fit together with script
287cdf0e10cSrcweir# engine lifetime management
288cdf0e10cSrcweir#----------------------------------
289cdf0e10cSrcweir#g_scriptContext = ScriptContext( uno.getComponentContext(), None )
290cdf0e10cSrcweir#g_modules = {}
291cdf0e10cSrcweir#def getModuleByUrl( url, sfa ):
292cdf0e10cSrcweir#    entry =  g_modules.get(url)
293cdf0e10cSrcweir#    load = True
294cdf0e10cSrcweir#    lastRead = sfa.getDateTimeModified( url )
295cdf0e10cSrcweir#    if entry:
296cdf0e10cSrcweir#        if hasChanged( entry.lastRead, lastRead ):
297735dd73bSPedro Giffuni#            log.debug("file " + url + " has changed, reloading")
298cdf0e10cSrcweir#        else:
299cdf0e10cSrcweir#            load = False
30013cfd8dfSPedro Giffuni#
301cdf0e10cSrcweir#    if load:
302735dd73bSPedro Giffuni#        log.debug( "opening >" + url + "<" )
303cdf0e10cSrcweir#
304cdf0e10cSrcweir#        code = readTextFromStream( sfa.openFileRead( url ) )
30513cfd8dfSPedro Giffuni
306cdf0e10cSrcweir        # execute the module
307cdf0e10cSrcweir#        entry = ModuleEntry( lastRead, imp.new_module("ooo_script_framework") )
308cdf0e10cSrcweir#        entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = g_scriptContext
309cdf0e10cSrcweir#        entry.module.__file__ = url
310cdf0e10cSrcweir#        exec code in entry.module.__dict__
311cdf0e10cSrcweir#        g_modules[ url ] = entry
312735dd73bSPedro Giffuni#        log.debug( "mapped " + url + " to " + str( entry.module ) )
313cdf0e10cSrcweir#    return entry.module
314cdf0e10cSrcweir
315cdf0e10cSrcweirclass ProviderContext:
316cdf0e10cSrcweir    def __init__( self, storageType, sfa, uriHelper, scriptContext ):
317cdf0e10cSrcweir        self.storageType = storageType
318cdf0e10cSrcweir        self.sfa = sfa
319cdf0e10cSrcweir        self.uriHelper = uriHelper
320cdf0e10cSrcweir        self.scriptContext = scriptContext
321cdf0e10cSrcweir        self.modules = {}
322cdf0e10cSrcweir        self.rootUrl = None
323cdf0e10cSrcweir        self.mapPackageName2Path = None
324cdf0e10cSrcweir
325cdf0e10cSrcweir    def getTransientPartFromUrl( self, url ):
326cdf0e10cSrcweir        rest = url.replace( self.rootUrl , "",1 ).replace( "/","",1)
327cdf0e10cSrcweir        return rest[0:rest.find("/")]
32813cfd8dfSPedro Giffuni
329cdf0e10cSrcweir    def getPackageNameFromUrl( self, url ):
330cdf0e10cSrcweir        rest = url.replace( self.rootUrl , "",1 ).replace( "/","",1)
331cdf0e10cSrcweir        start = rest.find("/") +1
332cdf0e10cSrcweir        return rest[start:rest.find("/",start)]
33313cfd8dfSPedro Giffuni
33413cfd8dfSPedro Giffuni
335cdf0e10cSrcweir    def removePackageByUrl( self, url ):
33615745147SPedro Giffuni        items = list(self.mapPackageName2Path.items())
337cdf0e10cSrcweir        for i in items:
338cdf0e10cSrcweir            if url in i[1].pathes:
339cdf0e10cSrcweir                self.mapPackageName2Path.pop(i[0])
340cdf0e10cSrcweir                break
341cdf0e10cSrcweir
342cdf0e10cSrcweir    def addPackageByUrl( self, url ):
343cdf0e10cSrcweir        packageName = self.getPackageNameFromUrl( url )
344cdf0e10cSrcweir        transientPart = self.getTransientPartFromUrl( url )
345735dd73bSPedro Giffuni        log.debug( "addPackageByUrl : " + packageName + ", " + transientPart + "("+url+")" + ", rootUrl="+self.rootUrl )
34615745147SPedro Giffuni        if packageName in self.mapPackageName2Path:
347cdf0e10cSrcweir            package = self.mapPackageName2Path[ packageName ]
348cdf0e10cSrcweir            package.pathes = package.pathes + (url, )
349cdf0e10cSrcweir        else:
350cdf0e10cSrcweir            package = Package( (url,), transientPart)
351cdf0e10cSrcweir            self.mapPackageName2Path[ packageName ] = package
35213cfd8dfSPedro Giffuni
353cdf0e10cSrcweir    def isUrlInPackage( self, url ):
35415745147SPedro Giffuni        values = list(self.mapPackageName2Path.values())
355cdf0e10cSrcweir        for i in values:
35613cfd8dfSPedro Giffuni#           print "checking " + url + " in " + str(i.pathes)
357cdf0e10cSrcweir            if url in i.pathes:
35813cfd8dfSPedro Giffuni                return True
359cdf0e10cSrcweir#        print "false"
360cdf0e10cSrcweir        return False
36113cfd8dfSPedro Giffuni
362cdf0e10cSrcweir    def setPackageAttributes( self, mapPackageName2Path, rootUrl ):
363cdf0e10cSrcweir        self.mapPackageName2Path = mapPackageName2Path
364cdf0e10cSrcweir        self.rootUrl = rootUrl
36513cfd8dfSPedro Giffuni
366cdf0e10cSrcweir    def getPersistentUrlFromStorageUrl( self, url ):
367cdf0e10cSrcweir        # package name is the second directory
368cdf0e10cSrcweir        ret = url
369cdf0e10cSrcweir        if self.rootUrl:
370cdf0e10cSrcweir            pos = len( self.rootUrl) +1
371cdf0e10cSrcweir            ret = url[0:pos]+url[url.find("/",pos)+1:len(url)]
372735dd73bSPedro Giffuni        log.debug( "getPersistentUrlFromStorageUrl " + url +  " -> "+ ret)
373cdf0e10cSrcweir        return ret
374cdf0e10cSrcweir
375cdf0e10cSrcweir    def getStorageUrlFromPersistentUrl( self, url):
376cdf0e10cSrcweir        ret = url
377cdf0e10cSrcweir        if self.rootUrl:
378cdf0e10cSrcweir            pos = len(self.rootUrl)+1
379cdf0e10cSrcweir            packageName = url[pos:url.find("/",pos+1)]
380cdf0e10cSrcweir            package = self.mapPackageName2Path[ packageName ]
381cdf0e10cSrcweir            ret = url[0:pos]+ package.transientPathElement + "/" + url[pos:len(url)]
382735dd73bSPedro Giffuni        log.debug( "getStorageUrlFromPersistentUrl " + url + " -> "+ ret)
383cdf0e10cSrcweir        return ret
384cdf0e10cSrcweir
385cdf0e10cSrcweir    def getFuncsByUrl( self, url ):
386cdf0e10cSrcweir        src = readTextFromStream( self.sfa.openFileRead( url ) )
387cdf0e10cSrcweir        checkForPythonPathBesideScript( url[0:url.rfind('/')] )
388cdf0e10cSrcweir        src = ensureSourceState( src )
389cdf0e10cSrcweir
390cdf0e10cSrcweir        allFuncs = []
391cdf0e10cSrcweir        g_exportedScripts = []
392cdf0e10cSrcweir
39313cfd8dfSPedro Giffuni        a = ast.parse(src, url)
39413cfd8dfSPedro Giffuni
39513cfd8dfSPedro Giffuni        if isinstance(a, ast.Module):
39613cfd8dfSPedro Giffuni            for node in a.body:
39713cfd8dfSPedro Giffuni                if isinstance(node, ast.FunctionDef):
39813cfd8dfSPedro Giffuni                    allFuncs.append(node.name)
39913cfd8dfSPedro Giffuni                elif isinstance(node, ast.Assign):
40013cfd8dfSPedro Giffuni                    is_exported = False
40113cfd8dfSPedro Giffuni                    for subnode in node.targets:
40213cfd8dfSPedro Giffuni                        if isinstance(subnode, ast.Name) and \
40313cfd8dfSPedro Giffuni                            subnode.id == "g_exportedScripts":
40413cfd8dfSPedro Giffuni                            is_exported = True
40513cfd8dfSPedro Giffuni                            break
40613cfd8dfSPedro Giffuni                    if is_exported:
40713cfd8dfSPedro Giffuni                        value_node = node.value
40813cfd8dfSPedro Giffuni                        if isinstance(value_node, ast.List) or \
40913cfd8dfSPedro Giffuni                            isinstance(value_node, ast.Tuple):
41013cfd8dfSPedro Giffuni                            for elt in value_node.elts:
41113cfd8dfSPedro Giffuni                                if isinstance(elt, ast.Str):
41213cfd8dfSPedro Giffuni                                    g_exportedScripts.append(elt.s)
41313cfd8dfSPedro Giffuni                                elif isinstance(elt, ast.Name):
41413cfd8dfSPedro Giffuni                                    g_exportedScripts.append(elt.id)
41513cfd8dfSPedro Giffuni                        elif isinstance(value_node, ast.Str):
41613cfd8dfSPedro Giffuni                            g_exportedScripts.append(value_node.s)
41713cfd8dfSPedro Giffuni                        elif isinstance(value_node, ast.Name):
41813cfd8dfSPedro Giffuni                            g_exportedScripts.append(value_node.id)
41913cfd8dfSPedro Giffuni                        return g_exportedScripts
420cdf0e10cSrcweir        return allFuncs
42113cfd8dfSPedro Giffuni
422cdf0e10cSrcweir    def getModuleByUrl( self, url ):
423cdf0e10cSrcweir        entry =  self.modules.get(url)
424cdf0e10cSrcweir        load = True
425cdf0e10cSrcweir        lastRead = self.sfa.getDateTimeModified( url )
426cdf0e10cSrcweir        if entry:
427cdf0e10cSrcweir            if hasChanged( entry.lastRead, lastRead ):
428735dd73bSPedro Giffuni                log.debug( "file " + url + " has changed, reloading" )
429cdf0e10cSrcweir            else:
430cdf0e10cSrcweir                load = False
43113cfd8dfSPedro Giffuni
432cdf0e10cSrcweir        if load:
433735dd73bSPedro Giffuni            log.debug( "opening >" + url + "<" )
43413cfd8dfSPedro Giffuni
435cdf0e10cSrcweir            src = readTextFromStream( self.sfa.openFileRead( url ) )
436cdf0e10cSrcweir            checkForPythonPathBesideScript( url[0:url.rfind('/')] )
43713cfd8dfSPedro Giffuni            src = ensureSourceState( src )
43813cfd8dfSPedro Giffuni
439cdf0e10cSrcweir            # execute the module
440cdf0e10cSrcweir            entry = ModuleEntry( lastRead, imp.new_module("ooo_script_framework") )
441cdf0e10cSrcweir            entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.scriptContext
442cdf0e10cSrcweir
443cdf0e10cSrcweir            code = None
444cdf0e10cSrcweir            if url.startswith( "file:" ):
445cdf0e10cSrcweir                code = compile( src, encfile(uno.fileUrlToSystemPath( url ) ), "exec" )
446cdf0e10cSrcweir            else:
447cdf0e10cSrcweir                code = compile( src, url, "exec" )
44815745147SPedro Giffuni            exec(code, entry.module.__dict__)
449cdf0e10cSrcweir            entry.module.__file__ = url
450cdf0e10cSrcweir            self.modules[ url ] = entry
451735dd73bSPedro Giffuni            log.debug( "mapped " + url + " to " + str( entry.module ) )
452cdf0e10cSrcweir        return  entry.module
45313cfd8dfSPedro Giffuni
454cdf0e10cSrcweir#--------------------------------------------------
455cdf0e10cSrcweirdef isScript( candidate ):
456cdf0e10cSrcweir    ret = False
457cdf0e10cSrcweir    if isinstance( candidate, type(isScript) ):
458cdf0e10cSrcweir        ret = True
459cdf0e10cSrcweir    return ret
46013cfd8dfSPedro Giffuni
461cdf0e10cSrcweir#-------------------------------------------------------
462cdf0e10cSrcweirclass ScriptBrowseNode( unohelper.Base, XBrowseNode , XPropertySet, XInvocation, XActionListener ):
463cdf0e10cSrcweir    def __init__( self, provCtx, uri, fileName, funcName ):
464cdf0e10cSrcweir        self.fileName = fileName
465cdf0e10cSrcweir        self.funcName = funcName
466cdf0e10cSrcweir        self.provCtx = provCtx
467cdf0e10cSrcweir        self.uri = uri
46813cfd8dfSPedro Giffuni
469cdf0e10cSrcweir    def getName( self ):
470cdf0e10cSrcweir        return self.funcName
471cdf0e10cSrcweir
472cdf0e10cSrcweir    def getChildNodes(self):
473cdf0e10cSrcweir        return ()
474cdf0e10cSrcweir
475cdf0e10cSrcweir    def hasChildNodes(self):
476cdf0e10cSrcweir        return False
47713cfd8dfSPedro Giffuni
478cdf0e10cSrcweir    def getType( self):
479cdf0e10cSrcweir        return SCRIPT
480cdf0e10cSrcweir
481cdf0e10cSrcweir    def getPropertyValue( self, name ):
482cdf0e10cSrcweir        ret = None
483cdf0e10cSrcweir        try:
484cdf0e10cSrcweir            if name == "URI":
485cdf0e10cSrcweir                ret = self.provCtx.uriHelper.getScriptURI(
486cdf0e10cSrcweir                    self.provCtx.getPersistentUrlFromStorageUrl( self.uri + "$" + self.funcName ) )
487cdf0e10cSrcweir            elif name == "Editable" and ENABLE_EDIT_DIALOG:
488cdf0e10cSrcweir                ret = not self.provCtx.sfa.isReadOnly( self.uri )
48913cfd8dfSPedro Giffuni
490735dd73bSPedro Giffuni            log.debug( "ScriptBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) )
49115745147SPedro Giffuni        except Exception as e:
492cdf0e10cSrcweir            log.error( "ScriptBrowseNode.getPropertyValue error " + lastException2String())
493cdf0e10cSrcweir            raise
49413cfd8dfSPedro Giffuni
495cdf0e10cSrcweir        return ret
496cdf0e10cSrcweir    def setPropertyValue( self, name, value ):
497735dd73bSPedro Giffuni        log.debug( "ScriptBrowseNode.setPropertyValue called " + name + "=" +str(value ) )
498cdf0e10cSrcweir    def getPropertySetInfo( self ):
499735dd73bSPedro Giffuni        log.debug( "ScriptBrowseNode.getPropertySetInfo called "  )
500cdf0e10cSrcweir        return None
50113cfd8dfSPedro Giffuni
502cdf0e10cSrcweir    def getIntrospection( self ):
503cdf0e10cSrcweir        return None
504cdf0e10cSrcweir
505cdf0e10cSrcweir    def invoke( self, name, params, outparamindex, outparams ):
506cdf0e10cSrcweir        if name == "Editable":
507cdf0e10cSrcweir            servicename = "com.sun.star.awt.DialogProvider"
508cdf0e10cSrcweir            ctx = self.provCtx.scriptContext.getComponentContext()
509cdf0e10cSrcweir            dlgprov = ctx.ServiceManager.createInstanceWithContext(
510cdf0e10cSrcweir                servicename, ctx )
511cdf0e10cSrcweir
512cdf0e10cSrcweir            self.editor = dlgprov.createDialog(
513cdf0e10cSrcweir                "vnd.sun.star.script:" +
514cdf0e10cSrcweir                "ScriptBindingLibrary.MacroEditor?location=application")
515cdf0e10cSrcweir
516cdf0e10cSrcweir            code = readTextFromStream(self.provCtx.sfa.openFileRead(self.uri))
517cdf0e10cSrcweir            code = ensureSourceState( code )
518cdf0e10cSrcweir            self.editor.getControl("EditorTextField").setText(code)
519cdf0e10cSrcweir
520cdf0e10cSrcweir            self.editor.getControl("RunButton").setActionCommand("Run")
521cdf0e10cSrcweir            self.editor.getControl("RunButton").addActionListener(self)
522cdf0e10cSrcweir            self.editor.getControl("SaveButton").setActionCommand("Save")
523cdf0e10cSrcweir            self.editor.getControl("SaveButton").addActionListener(self)
524cdf0e10cSrcweir
525cdf0e10cSrcweir            self.editor.execute()
526cdf0e10cSrcweir
527cdf0e10cSrcweir        return None
528cdf0e10cSrcweir
529cdf0e10cSrcweir    def actionPerformed( self, event ):
530cdf0e10cSrcweir        try:
531cdf0e10cSrcweir            if event.ActionCommand == "Run":
532cdf0e10cSrcweir                code = self.editor.getControl("EditorTextField").getText()
533cdf0e10cSrcweir                code = ensureSourceState( code )
534cdf0e10cSrcweir                mod = imp.new_module("ooo_script_framework")
535cdf0e10cSrcweir                mod.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.provCtx.scriptContext
53615745147SPedro Giffuni                exec(code, mod.__dict__)
537cdf0e10cSrcweir                values = mod.__dict__.get( CALLABLE_CONTAINER_NAME , None )
538cdf0e10cSrcweir                if not values:
53915745147SPedro Giffuni                    values = list(mod.__dict__.values())
54013cfd8dfSPedro Giffuni
541cdf0e10cSrcweir                for i in values:
542cdf0e10cSrcweir                    if isScript( i ):
543cdf0e10cSrcweir                        i()
544cdf0e10cSrcweir                        break
54513cfd8dfSPedro Giffuni
546cdf0e10cSrcweir            elif event.ActionCommand == "Save":
547cdf0e10cSrcweir                toWrite = uno.ByteSequence(
548cdf0e10cSrcweir                    str(
549cdf0e10cSrcweir                    self.editor.getControl("EditorTextField").getText().encode(
550cdf0e10cSrcweir                    sys.getdefaultencoding())) )
551cdf0e10cSrcweir                copyUrl = self.uri + ".orig"
552cdf0e10cSrcweir                self.provCtx.sfa.move( self.uri, copyUrl )
553cdf0e10cSrcweir                out = self.provCtx.sfa.openFileWrite( self.uri )
554cdf0e10cSrcweir                out.writeBytes( toWrite )
555cdf0e10cSrcweir                out.close()
556cdf0e10cSrcweir                self.provCtx.sfa.kill( copyUrl )
557735dd73bSPedro Giffuni#                log.debug("Save is not implemented yet")
558cdf0e10cSrcweir#                text = self.editor.getControl("EditorTextField").getText()
559735dd73bSPedro Giffuni#                log.debug("Would save: " + text)
56015745147SPedro Giffuni        except Exception as e:
561cdf0e10cSrcweir            # TODO: add an error box here !
562cdf0e10cSrcweir            log.error( lastException2String() )
56313cfd8dfSPedro Giffuni
564cdf0e10cSrcweir
565cdf0e10cSrcweir    def setValue( self, name, value ):
566cdf0e10cSrcweir        return None
567cdf0e10cSrcweir
568cdf0e10cSrcweir    def getValue( self, name ):
569cdf0e10cSrcweir        return None
570cdf0e10cSrcweir
571cdf0e10cSrcweir    def hasMethod( self, name ):
572cdf0e10cSrcweir        return False
573cdf0e10cSrcweir
574cdf0e10cSrcweir    def hasProperty( self, name ):
575cdf0e10cSrcweir        return False
576cdf0e10cSrcweir
57713cfd8dfSPedro Giffuni
578cdf0e10cSrcweir#-------------------------------------------------------
579cdf0e10cSrcweirclass FileBrowseNode( unohelper.Base, XBrowseNode ):
580cdf0e10cSrcweir    def __init__( self, provCtx, uri , name ):
581cdf0e10cSrcweir        self.provCtx = provCtx
582cdf0e10cSrcweir        self.uri = uri
583cdf0e10cSrcweir        self.name = name
584cdf0e10cSrcweir        self.funcnames = None
58513cfd8dfSPedro Giffuni
586cdf0e10cSrcweir    def getName( self ):
587cdf0e10cSrcweir        return self.name
58813cfd8dfSPedro Giffuni
589cdf0e10cSrcweir    def getChildNodes(self):
590cdf0e10cSrcweir        ret = ()
591cdf0e10cSrcweir        try:
592cdf0e10cSrcweir            self.funcnames = self.provCtx.getFuncsByUrl( self.uri )
59313cfd8dfSPedro Giffuni
594cdf0e10cSrcweir            scriptNodeList = []
595cdf0e10cSrcweir            for i in self.funcnames:
596cdf0e10cSrcweir                scriptNodeList.append(
597cdf0e10cSrcweir                    ScriptBrowseNode(
598cdf0e10cSrcweir                    self.provCtx, self.uri, self.name, i ))
599cdf0e10cSrcweir            ret = tuple( scriptNodeList )
600735dd73bSPedro Giffuni            log.debug( "returning " +str(len(ret)) + " ScriptChildNodes on " + self.uri )
60115745147SPedro Giffuni        except Exception as e:
602cdf0e10cSrcweir            text = lastException2String()
603cdf0e10cSrcweir            log.error( "Error while evaluating " + self.uri + ":" + text )
604cdf0e10cSrcweir            raise
605cdf0e10cSrcweir        return ret
606cdf0e10cSrcweir
607cdf0e10cSrcweir    def hasChildNodes(self):
608cdf0e10cSrcweir        try:
609cdf0e10cSrcweir            return len(self.getChildNodes()) > 0
61015745147SPedro Giffuni        except Exception as e:
611cdf0e10cSrcweir            return False
61213cfd8dfSPedro Giffuni
613cdf0e10cSrcweir    def getType( self):
614cdf0e10cSrcweir        return CONTAINER
615cdf0e10cSrcweir
61613cfd8dfSPedro Giffuni
617cdf0e10cSrcweir
618cdf0e10cSrcweirclass DirBrowseNode( unohelper.Base, XBrowseNode ):
619cdf0e10cSrcweir    def __init__( self, provCtx, name, rootUrl ):
620cdf0e10cSrcweir        self.provCtx = provCtx
621cdf0e10cSrcweir        self.name = name
622cdf0e10cSrcweir        self.rootUrl = rootUrl
623cdf0e10cSrcweir
624cdf0e10cSrcweir    def getName( self ):
625cdf0e10cSrcweir        return self.name
626cdf0e10cSrcweir
627cdf0e10cSrcweir    def getChildNodes( self ):
628cdf0e10cSrcweir        try:
629735dd73bSPedro Giffuni            log.debug( "DirBrowseNode.getChildNodes called for " + self.rootUrl )
630cdf0e10cSrcweir            contents = self.provCtx.sfa.getFolderContents( self.rootUrl, True )
631cdf0e10cSrcweir            browseNodeList = []
632cdf0e10cSrcweir            for i in contents:
633cdf0e10cSrcweir                if i.endswith( ".py" ):
634735dd73bSPedro Giffuni                    log.debug( "adding filenode " + i )
635cdf0e10cSrcweir                    browseNodeList.append(
636cdf0e10cSrcweir                        FileBrowseNode( self.provCtx, i, i[i.rfind("/")+1:len(i)-3] ) )
637cdf0e10cSrcweir                elif self.provCtx.sfa.isFolder( i ) and not i.endswith("/pythonpath"):
638735dd73bSPedro Giffuni                    log.debug( "adding DirBrowseNode " + i )
639cdf0e10cSrcweir                    browseNodeList.append( DirBrowseNode( self.provCtx, i[i.rfind("/")+1:len(i)],i))
640cdf0e10cSrcweir            return tuple( browseNodeList )
64115745147SPedro Giffuni        except Exception as e:
642cdf0e10cSrcweir            text = lastException2String()
643cdf0e10cSrcweir            log.error( "DirBrowseNode error: " + str(e) + " while evaluating " + self.rootUrl)
644cdf0e10cSrcweir            log.error( text)
645cdf0e10cSrcweir            return ()
646cdf0e10cSrcweir
647cdf0e10cSrcweir    def hasChildNodes( self ):
648cdf0e10cSrcweir        return True
649cdf0e10cSrcweir
650cdf0e10cSrcweir    def getType( self ):
651cdf0e10cSrcweir        return CONTAINER
652cdf0e10cSrcweir
653cdf0e10cSrcweir    def getScript( self, uri ):
654cdf0e10cSrcweir        log.debug( "DirBrowseNode getScript " + uri + " invoked" )
655cdf0e10cSrcweir        raise IllegalArgumentException( "DirBrowseNode couldn't instantiate script " + uri , self , 0 )
656cdf0e10cSrcweir
657cdf0e10cSrcweir
658cdf0e10cSrcweirclass ManifestHandler( XDocumentHandler, unohelper.Base ):
659cdf0e10cSrcweir    def __init__( self, rootUrl ):
660cdf0e10cSrcweir        self.rootUrl = rootUrl
66113cfd8dfSPedro Giffuni
662cdf0e10cSrcweir    def startDocument( self ):
663cdf0e10cSrcweir        self.urlList = []
66413cfd8dfSPedro Giffuni
665cdf0e10cSrcweir    def endDocument( self ):
666cdf0e10cSrcweir        pass
66713cfd8dfSPedro Giffuni
668cdf0e10cSrcweir    def startElement( self , name, attlist):
669cdf0e10cSrcweir        if name == "manifest:file-entry":
670cdf0e10cSrcweir            if attlist.getValueByName( "manifest:media-type" ) == "application/vnd.sun.star.framework-script":
671cdf0e10cSrcweir                self.urlList.append(
672cdf0e10cSrcweir                    self.rootUrl + "/" + attlist.getValueByName( "manifest:full-path" ) )
673cdf0e10cSrcweir
674cdf0e10cSrcweir    def endElement( self, name ):
675cdf0e10cSrcweir        pass
676cdf0e10cSrcweir
677cdf0e10cSrcweir    def characters ( self, chars ):
678cdf0e10cSrcweir        pass
679cdf0e10cSrcweir
680cdf0e10cSrcweir    def ignoreableWhitespace( self, chars ):
681cdf0e10cSrcweir        pass
682cdf0e10cSrcweir
683cdf0e10cSrcweir    def setDocumentLocator( self, locator ):
684cdf0e10cSrcweir        pass
685cdf0e10cSrcweir
686cdf0e10cSrcweirdef isPyFileInPath( sfa, path ):
687cdf0e10cSrcweir    ret = False
688cdf0e10cSrcweir    contents = sfa.getFolderContents( path, True )
689cdf0e10cSrcweir    for i in contents:
690cdf0e10cSrcweir        if sfa.isFolder(i):
691cdf0e10cSrcweir            ret = isPyFileInPath(sfa,i)
692cdf0e10cSrcweir        else:
693cdf0e10cSrcweir            if i.endswith(".py"):
694cdf0e10cSrcweir                ret = True
695cdf0e10cSrcweir        if ret:
696cdf0e10cSrcweir            break
697cdf0e10cSrcweir    return ret
698cdf0e10cSrcweir
69913cfd8dfSPedro Giffuni# extracts META-INF directory from
700cdf0e10cSrcweirdef getPathesFromPackage( rootUrl, sfa ):
701cdf0e10cSrcweir    ret = ()
702cdf0e10cSrcweir    try:
70313cfd8dfSPedro Giffuni        fileUrl = rootUrl + "/META-INF/manifest.xml"
704cdf0e10cSrcweir        inputStream = sfa.openFileRead( fileUrl )
705cdf0e10cSrcweir        parser = uno.getComponentContext().ServiceManager.createInstance( "com.sun.star.xml.sax.Parser" )
706cdf0e10cSrcweir        handler = ManifestHandler( rootUrl )
707cdf0e10cSrcweir        parser.setDocumentHandler( handler )
708cdf0e10cSrcweir        parser.parseStream( InputSource( inputStream , "", fileUrl, fileUrl ) )
709cdf0e10cSrcweir        for i in tuple(handler.urlList):
710cdf0e10cSrcweir            if not isPyFileInPath( sfa, i ):
711cdf0e10cSrcweir                handler.urlList.remove(i)
712cdf0e10cSrcweir        ret = tuple( handler.urlList )
71315745147SPedro Giffuni    except UnoException as e:
714cdf0e10cSrcweir        text = lastException2String()
715cdf0e10cSrcweir        log.debug( "getPathesFromPackage " + fileUrl + " Exception: " +text )
716cdf0e10cSrcweir        pass
717cdf0e10cSrcweir    return ret
71813cfd8dfSPedro Giffuni
719cdf0e10cSrcweir
720cdf0e10cSrcweirclass Package:
721cdf0e10cSrcweir    def __init__( self, pathes, transientPathElement ):
722cdf0e10cSrcweir        self.pathes = pathes
723cdf0e10cSrcweir        self.transientPathElement = transientPathElement
724cdf0e10cSrcweir
725cdf0e10cSrcweirclass DummyInteractionHandler( unohelper.Base, XInteractionHandler ):
726cdf0e10cSrcweir    def __init__( self ):
727cdf0e10cSrcweir        pass
728cdf0e10cSrcweir    def handle( self, event):
729735dd73bSPedro Giffuni        log.debug( "pythonscript: DummyInteractionHandler.handle " + str( event ) )
730cdf0e10cSrcweir
731cdf0e10cSrcweirclass DummyProgressHandler( unohelper.Base, XProgressHandler ):
732cdf0e10cSrcweir    def __init__( self ):
733cdf0e10cSrcweir        pass
73413cfd8dfSPedro Giffuni
73513cfd8dfSPedro Giffuni    def push( self,status ):
736735dd73bSPedro Giffuni        log.debug( "pythonscript: DummyProgressHandler.push " + str( status ) )
73713cfd8dfSPedro Giffuni    def update( self,status ):
738735dd73bSPedro Giffuni        log.debug( "pythonscript: DummyProgressHandler.update " + str( status ) )
73913cfd8dfSPedro Giffuni    def pop( self ):
740735dd73bSPedro Giffuni        log.debug( "pythonscript: DummyProgressHandler.push " + str( event ) )
741cdf0e10cSrcweir
742cdf0e10cSrcweirclass CommandEnvironment(unohelper.Base, XCommandEnvironment):
743cdf0e10cSrcweir    def __init__( self ):
744cdf0e10cSrcweir        self.progressHandler = DummyProgressHandler()
745cdf0e10cSrcweir        self.interactionHandler = DummyInteractionHandler()
746cdf0e10cSrcweir    def getInteractionHandler( self ):
747cdf0e10cSrcweir        return self.interactionHandler
748cdf0e10cSrcweir    def getProgressHandler( self ):
749cdf0e10cSrcweir        return self.progressHandler
750cdf0e10cSrcweir
751cdf0e10cSrcweir#maybe useful for debugging purposes
752cdf0e10cSrcweir#class ModifyListener( unohelper.Base, XModifyListener ):
753cdf0e10cSrcweir#    def __init__( self ):
754cdf0e10cSrcweir#        pass
755cdf0e10cSrcweir#    def modified( self, event ):
756735dd73bSPedro Giffuni#        log.debug( "pythonscript: ModifyListener.modified " + str( event ) )
757cdf0e10cSrcweir#    def disposing( self, event ):
758735dd73bSPedro Giffuni#        log.debug( "pythonscript: ModifyListener.disposing " + str( event ) )
75961c9e2f8SAriel Constenla-Haile
76061c9e2f8SAriel Constenla-Hailedef getModelFromDocUrl(ctx, url):
76161c9e2f8SAriel Constenla-Haile    """Get document model from document url."""
76261c9e2f8SAriel Constenla-Haile    doc = None
76361c9e2f8SAriel Constenla-Haile    args = ("Local", "Office")
76461c9e2f8SAriel Constenla-Haile    ucb = ctx.getServiceManager().createInstanceWithArgumentsAndContext(
76561c9e2f8SAriel Constenla-Haile        "com.sun.star.ucb.UniversalContentBroker", args, ctx)
76661c9e2f8SAriel Constenla-Haile    identifier = ucb.createContentIdentifier(url)
76761c9e2f8SAriel Constenla-Haile    content = ucb.queryContent(identifier)
76861c9e2f8SAriel Constenla-Haile    p = Property()
76961c9e2f8SAriel Constenla-Haile    p.Name = "DocumentModel"
77061c9e2f8SAriel Constenla-Haile    p.Handle = -1
77113cfd8dfSPedro Giffuni
77261c9e2f8SAriel Constenla-Haile    c = Command()
77361c9e2f8SAriel Constenla-Haile    c.Handle = -1
77461c9e2f8SAriel Constenla-Haile    c.Name = "getPropertyValues"
77561c9e2f8SAriel Constenla-Haile    c.Argument = uno.Any("[]com.sun.star.beans.Property", (p,))
77613cfd8dfSPedro Giffuni
77761c9e2f8SAriel Constenla-Haile    env = CommandEnvironment()
77861c9e2f8SAriel Constenla-Haile    try:
77961c9e2f8SAriel Constenla-Haile        ret = content.execute(c, 0, env)
78061c9e2f8SAriel Constenla-Haile        doc = ret.getObject(1, None)
78115745147SPedro Giffuni    except Exception as e:
78261c9e2f8SAriel Constenla-Haile        log.isErrorLevel() and log.error("getModelFromDocUrl: %s" % url)
78361c9e2f8SAriel Constenla-Haile    return doc
78461c9e2f8SAriel Constenla-Haile
785cdf0e10cSrcweirdef mapStorageType2PackageContext( storageType ):
786cdf0e10cSrcweir    ret = storageType
787cdf0e10cSrcweir    if( storageType == "share:uno_packages" ):
788cdf0e10cSrcweir        ret = "shared"
789cdf0e10cSrcweir    if( storageType == "user:uno_packages" ):
790cdf0e10cSrcweir        ret = "user"
791cdf0e10cSrcweir    return ret
792cdf0e10cSrcweir
793cdf0e10cSrcweirdef getPackageName2PathMap( sfa, storageType ):
794cdf0e10cSrcweir    ret = {}
795cdf0e10cSrcweir    packageManagerFactory = uno.getComponentContext().getValueByName(
796cdf0e10cSrcweir        "/singletons/com.sun.star.deployment.thePackageManagerFactory" )
797cdf0e10cSrcweir    packageManager = packageManagerFactory.getPackageManager(
798cdf0e10cSrcweir        mapStorageType2PackageContext(storageType))
799cdf0e10cSrcweir#    packageManager.addModifyListener( ModifyListener() )
800735dd73bSPedro Giffuni    log.debug( "pythonscript: getPackageName2PathMap start getDeployedPackages" )
801cdf0e10cSrcweir    packages = packageManager.getDeployedPackages(
802cdf0e10cSrcweir        packageManager.createAbortChannel(), CommandEnvironment( ) )
803735dd73bSPedro Giffuni    log.debug( "pythonscript: getPackageName2PathMap end getDeployedPackages (" + str(len(packages))+")" )
804cdf0e10cSrcweir
805cdf0e10cSrcweir    for i in packages:
806735dd73bSPedro Giffuni        log.debug( "inspecting package " + i.Name + "("+i.Identifier.Value+")" )
807cdf0e10cSrcweir        transientPathElement = penultimateElement( i.URL )
808cdf0e10cSrcweir        j = expandUri( i.URL )
809cdf0e10cSrcweir        pathes = getPathesFromPackage( j, sfa )
810cdf0e10cSrcweir        if len( pathes ) > 0:
811cdf0e10cSrcweir            # map package name to url, we need this later
812cdf0e10cSrcweir            log.isErrorLevel() and log.error( "adding Package " + transientPathElement + " " + str( pathes ) )
813cdf0e10cSrcweir            ret[ lastElement( j ) ] = Package( pathes, transientPathElement )
814cdf0e10cSrcweir    return ret
815cdf0e10cSrcweir
816cdf0e10cSrcweirdef penultimateElement( aStr ):
817cdf0e10cSrcweir    lastSlash = aStr.rindex("/")
818cdf0e10cSrcweir    penultimateSlash = aStr.rindex("/",0,lastSlash-1)
819cdf0e10cSrcweir    return  aStr[ penultimateSlash+1:lastSlash ]
820cdf0e10cSrcweir
821cdf0e10cSrcweirdef lastElement( aStr):
822cdf0e10cSrcweir    return aStr[ aStr.rfind( "/" )+1:len(aStr)]
823cdf0e10cSrcweir
824cdf0e10cSrcweirclass PackageBrowseNode( unohelper.Base, XBrowseNode ):
825cdf0e10cSrcweir    def __init__( self, provCtx, name, rootUrl ):
826cdf0e10cSrcweir        self.provCtx = provCtx
827cdf0e10cSrcweir        self.name = name
828cdf0e10cSrcweir        self.rootUrl = rootUrl
829cdf0e10cSrcweir
830cdf0e10cSrcweir    def getName( self ):
831cdf0e10cSrcweir        return self.name
832cdf0e10cSrcweir
833cdf0e10cSrcweir    def getChildNodes( self ):
83415745147SPedro Giffuni        items = list(self.provCtx.mapPackageName2Path.items())
835cdf0e10cSrcweir        browseNodeList = []
836cdf0e10cSrcweir        for i in items:
837cdf0e10cSrcweir            if len( i[1].pathes ) == 1:
838cdf0e10cSrcweir                browseNodeList.append(
839cdf0e10cSrcweir                    DirBrowseNode( self.provCtx, i[0], i[1].pathes[0] ))
840cdf0e10cSrcweir            else:
841cdf0e10cSrcweir                for j in i[1].pathes:
842cdf0e10cSrcweir                    browseNodeList.append(
843cdf0e10cSrcweir                        DirBrowseNode( self.provCtx, i[0]+"."+lastElement(j), j ) )
844cdf0e10cSrcweir        return tuple( browseNodeList )
845cdf0e10cSrcweir
846cdf0e10cSrcweir    def hasChildNodes( self ):
847cdf0e10cSrcweir        return len( self.mapPackageName2Path ) > 0
848cdf0e10cSrcweir
849cdf0e10cSrcweir    def getType( self ):
850cdf0e10cSrcweir        return CONTAINER
851cdf0e10cSrcweir
852cdf0e10cSrcweir    def getScript( self, uri ):
853cdf0e10cSrcweir        log.debug( "DirBrowseNode getScript " + uri + " invoked" )
854cdf0e10cSrcweir        raise IllegalArgumentException( "PackageBrowseNode couldn't instantiate script " + uri , self , 0 )
855cdf0e10cSrcweir
856cdf0e10cSrcweir
857cdf0e10cSrcweir
858cdf0e10cSrcweir
859cdf0e10cSrcweirclass PythonScript( unohelper.Base, XScript ):
860cdf0e10cSrcweir    def __init__( self, func, mod ):
861cdf0e10cSrcweir        self.func = func
862cdf0e10cSrcweir        self.mod = mod
863cdf0e10cSrcweir    def invoke(self, args, out, outindex ):
864735dd73bSPedro Giffuni        log.debug( "PythonScript.invoke " + str( args ) )
865cdf0e10cSrcweir        try:
866cdf0e10cSrcweir            ret = self.func( *args )
86715745147SPedro Giffuni        except UnoException as e:
868cdf0e10cSrcweir            # UNO Exception continue to fly ...
869cdf0e10cSrcweir            text = lastException2String()
870cdf0e10cSrcweir            complete = "Error during invoking function " + \
871cdf0e10cSrcweir                str(self.func.__name__) + " in module " + \
872cdf0e10cSrcweir                self.mod.__file__ + " (" + text + ")"
873735dd73bSPedro Giffuni            log.debug( complete )
874cdf0e10cSrcweir            # some people may beat me up for modifying the exception text,
875cdf0e10cSrcweir            # but otherwise office just shows
876cdf0e10cSrcweir            # the type name and message text with no more information,
87713cfd8dfSPedro Giffuni            # this is really bad for most users.
878cdf0e10cSrcweir            e.Message = e.Message + " (" + complete + ")"
879cdf0e10cSrcweir            raise
88015745147SPedro Giffuni        except Exception as e:
881cdf0e10cSrcweir            # General python exception are converted to uno RuntimeException
882cdf0e10cSrcweir            text = lastException2String()
883cdf0e10cSrcweir            complete = "Error during invoking function " + \
884cdf0e10cSrcweir                str(self.func.__name__) + " in module " + \
885cdf0e10cSrcweir                self.mod.__file__ + " (" + text + ")"
886735dd73bSPedro Giffuni            log.debug( complete )
887cdf0e10cSrcweir            raise RuntimeException( complete , self )
888735dd73bSPedro Giffuni        log.debug( "PythonScript.invoke ret = " + str( ret ) )
889cdf0e10cSrcweir        return ret, (), ()
890cdf0e10cSrcweir
891cdf0e10cSrcweirdef expandUri(  uri ):
892cdf0e10cSrcweir    if uri.startswith( "vnd.sun.star.expand:" ):
893cdf0e10cSrcweir        uri = uri.replace( "vnd.sun.star.expand:", "",1)
894cdf0e10cSrcweir        uri = uno.getComponentContext().getByName(
895cdf0e10cSrcweir                    "/singletons/com.sun.star.util.theMacroExpander" ).expandMacros( uri )
896cdf0e10cSrcweir    if uri.startswith( "file:" ):
897cdf0e10cSrcweir        uri = uno.absolutize("",uri)   # necessary to get rid of .. in uri
898cdf0e10cSrcweir    return uri
89913cfd8dfSPedro Giffuni
900cdf0e10cSrcweir#--------------------------------------------------------------
901cdf0e10cSrcweirclass PythonScriptProvider( unohelper.Base, XBrowseNode, XScriptProvider, XNameContainer):
902cdf0e10cSrcweir    def __init__( self, ctx, *args ):
903cdf0e10cSrcweir        if log.isDebugLevel():
904cdf0e10cSrcweir            mystr = ""
905cdf0e10cSrcweir            for i in args:
906cdf0e10cSrcweir                if len(mystr) > 0:
907cdf0e10cSrcweir                    mystr = mystr +","
908cdf0e10cSrcweir                mystr = mystr + str(i)
909cdf0e10cSrcweir            log.debug( "Entering PythonScriptProvider.ctor" + mystr )
910cdf0e10cSrcweir
91161c9e2f8SAriel Constenla-Haile        doc = None
91261c9e2f8SAriel Constenla-Haile        inv = None
913cdf0e10cSrcweir        storageType = ""
91461c9e2f8SAriel Constenla-Haile
915cdf0e10cSrcweir        if isinstance(args[0],unicode ):
916cdf0e10cSrcweir            storageType = args[0]
91761c9e2f8SAriel Constenla-Haile            if storageType.startswith( "vnd.sun.star.tdoc" ):
91861c9e2f8SAriel Constenla-Haile                doc = getModelFromDocUrl(ctx, storageType)
919cdf0e10cSrcweir        else:
92061c9e2f8SAriel Constenla-Haile            inv = args[0]
92161c9e2f8SAriel Constenla-Haile            try:
92261c9e2f8SAriel Constenla-Haile                doc = inv.ScriptContainer
92361c9e2f8SAriel Constenla-Haile                content = ctx.getServiceManager().createInstanceWithContext(
92413cfd8dfSPedro Giffuni                    "com.sun.star.frame.TransientDocumentsDocumentContentFactory",
92561c9e2f8SAriel Constenla-Haile                    ctx).createDocumentContent(doc)
92661c9e2f8SAriel Constenla-Haile                storageType = content.getIdentifier().getContentIdentifier()
92715745147SPedro Giffuni            except Exception as e:
92861c9e2f8SAriel Constenla-Haile                text = lastException2String()
92961c9e2f8SAriel Constenla-Haile                log.error( text )
93061c9e2f8SAriel Constenla-Haile
931cdf0e10cSrcweir        isPackage = storageType.endswith( ":uno_packages" )
932cdf0e10cSrcweir
933cdf0e10cSrcweir        try:
934cdf0e10cSrcweir#            urlHelper = ctx.ServiceManager.createInstanceWithArgumentsAndContext(
935cdf0e10cSrcweir#                "com.sun.star.script.provider.ScriptURIHelper", (LANGUAGENAME, storageType), ctx)
936cdf0e10cSrcweir            urlHelper = MyUriHelper( ctx, storageType )
937735dd73bSPedro Giffuni            log.debug( "got urlHelper " + str( urlHelper ) )
93813cfd8dfSPedro Giffuni
939cdf0e10cSrcweir            rootUrl = expandUri( urlHelper.getRootStorageURI() )
940735dd73bSPedro Giffuni            log.debug( storageType + " transformed to " + rootUrl )
941cdf0e10cSrcweir
942cdf0e10cSrcweir            ucbService = "com.sun.star.ucb.SimpleFileAccess"
943cdf0e10cSrcweir            sfa = ctx.ServiceManager.createInstanceWithContext( ucbService, ctx )
944cdf0e10cSrcweir            if not sfa:
945cdf0e10cSrcweir                log.debug("PythonScriptProvider couldn't instantiate " +ucbService)
946cdf0e10cSrcweir                raise RuntimeException(
947cdf0e10cSrcweir                    "PythonScriptProvider couldn't instantiate " +ucbService, self)
948cdf0e10cSrcweir            self.provCtx = ProviderContext(
94961c9e2f8SAriel Constenla-Haile                storageType, sfa, urlHelper, ScriptContext( uno.getComponentContext(), doc, inv ) )
950cdf0e10cSrcweir            if isPackage:
951cdf0e10cSrcweir                mapPackageName2Path = getPackageName2PathMap( sfa, storageType )
952cdf0e10cSrcweir                self.provCtx.setPackageAttributes( mapPackageName2Path , rootUrl )
953cdf0e10cSrcweir                self.dirBrowseNode = PackageBrowseNode( self.provCtx, LANGUAGENAME, rootUrl )
954cdf0e10cSrcweir            else:
955cdf0e10cSrcweir                self.dirBrowseNode = DirBrowseNode( self.provCtx, LANGUAGENAME, rootUrl )
95613cfd8dfSPedro Giffuni
95715745147SPedro Giffuni        except Exception as e:
958cdf0e10cSrcweir            text = lastException2String()
959cdf0e10cSrcweir            log.debug( "PythonScriptProvider could not be instantiated because of : " + text )
960cdf0e10cSrcweir            raise e
961cdf0e10cSrcweir
962cdf0e10cSrcweir    def getName( self ):
963cdf0e10cSrcweir        return self.dirBrowseNode.getName()
964cdf0e10cSrcweir
965cdf0e10cSrcweir    def getChildNodes( self ):
96613cfd8dfSPedro Giffuni        return self.dirBrowseNode.getChildNodes()
967cdf0e10cSrcweir
968cdf0e10cSrcweir    def hasChildNodes( self ):
969cdf0e10cSrcweir        return self.dirBrowseNode.hasChildNodes()
970cdf0e10cSrcweir
971cdf0e10cSrcweir    def getType( self ):
972cdf0e10cSrcweir        return self.dirBrowseNode.getType()
973cdf0e10cSrcweir
974cdf0e10cSrcweir    def getScript( self, uri ):
975cdf0e10cSrcweir        log.debug( "DirBrowseNode getScript " + uri + " invoked" )
97613cfd8dfSPedro Giffuni
977cdf0e10cSrcweir        raise IllegalArgumentException( "DirBrowseNode couldn't instantiate script " + uri , self , 0 )
978cdf0e10cSrcweir
979cdf0e10cSrcweir    def getScript( self, scriptUri ):
980cdf0e10cSrcweir        try:
981735dd73bSPedro Giffuni            log.debug( "getScript " + scriptUri + " invoked")
98213cfd8dfSPedro Giffuni
983cdf0e10cSrcweir            storageUri = self.provCtx.getStorageUrlFromPersistentUrl(
984cdf0e10cSrcweir                self.provCtx.uriHelper.getStorageURI(scriptUri) );
985735dd73bSPedro Giffuni            log.debug( "getScript: storageUri = " + storageUri)
986cdf0e10cSrcweir            fileUri = storageUri[0:storageUri.find( "$" )]
98713cfd8dfSPedro Giffuni            funcName = storageUri[storageUri.find( "$" )+1:len(storageUri)]
98813cfd8dfSPedro Giffuni
989cdf0e10cSrcweir            mod = self.provCtx.getModuleByUrl( fileUri )
990735dd73bSPedro Giffuni            log.debug( " got mod " + str(mod) )
99113cfd8dfSPedro Giffuni
992cdf0e10cSrcweir            func = mod.__dict__[ funcName ]
993cdf0e10cSrcweir
994735dd73bSPedro Giffuni            log.debug( "got func " + str( func ) )
995cdf0e10cSrcweir            return PythonScript( func, mod )
99615745147SPedro Giffuni        except Exception as e:
997cdf0e10cSrcweir            text = lastException2String()
998cdf0e10cSrcweir            log.error( text )
999cdf0e10cSrcweir            raise ScriptFrameworkErrorException( text, self, scriptUri, LANGUAGENAME, 0 )
100013cfd8dfSPedro Giffuni
1001cdf0e10cSrcweir
1002cdf0e10cSrcweir    # XServiceInfo
1003cdf0e10cSrcweir    def getSupportedServices( self ):
1004cdf0e10cSrcweir        return g_ImplementationHelper.getSupportedServices(g_implName)
1005cdf0e10cSrcweir
1006cdf0e10cSrcweir    def supportsService( self, ServiceName ):
1007cdf0e10cSrcweir        return g_ImplementationHelper.supportsService( g_implName, ServiceName )
1008cdf0e10cSrcweir
1009cdf0e10cSrcweir    def getImplementationName(self):
1010cdf0e10cSrcweir        return g_implName
1011cdf0e10cSrcweir
1012cdf0e10cSrcweir    def getByName( self, name ):
1013cdf0e10cSrcweir        log.debug( "getByName called" + str( name ))
1014cdf0e10cSrcweir        return None
1015cdf0e10cSrcweir
101613cfd8dfSPedro Giffuni
1017cdf0e10cSrcweir    def getElementNames( self ):
1018cdf0e10cSrcweir        log.debug( "getElementNames called")
1019cdf0e10cSrcweir        return ()
102013cfd8dfSPedro Giffuni
1021cdf0e10cSrcweir    def hasByName( self, name ):
1022cdf0e10cSrcweir        try:
1023cdf0e10cSrcweir            log.debug( "hasByName called " + str( name ))
1024cdf0e10cSrcweir            uri = expandUri(name)
1025cdf0e10cSrcweir            ret = self.provCtx.isUrlInPackage( uri )
1026cdf0e10cSrcweir            log.debug( "hasByName " + uri + " " +str( ret ) )
1027cdf0e10cSrcweir            return ret
102815745147SPedro Giffuni        except Exception as e:
1029cdf0e10cSrcweir            text = lastException2String()
1030cdf0e10cSrcweir            log.debug( "Error in hasByName:" +  text )
1031cdf0e10cSrcweir            return False
1032cdf0e10cSrcweir
1033cdf0e10cSrcweir    def removeByName( self, name ):
1034cdf0e10cSrcweir        log.debug( "removeByName called" + str( name ))
1035cdf0e10cSrcweir        uri = expandUri( name )
1036cdf0e10cSrcweir        if self.provCtx.isUrlInPackage( uri ):
1037cdf0e10cSrcweir            self.provCtx.removePackageByUrl( uri )
1038cdf0e10cSrcweir        else:
1039cdf0e10cSrcweir            log.debug( "removeByName unknown uri " + str( name ) + ", ignoring" )
1040cdf0e10cSrcweir            raise NoSuchElementException( uri + "is not in package" , self )
1041cdf0e10cSrcweir        log.debug( "removeByName called" + str( uri ) + " successful" )
104213cfd8dfSPedro Giffuni
1043cdf0e10cSrcweir    def insertByName( self, name, value ):
1044cdf0e10cSrcweir        log.debug( "insertByName called " + str( name ) + " " + str( value ))
1045cdf0e10cSrcweir        uri = expandUri( name )
1046cdf0e10cSrcweir        if isPyFileInPath( self.provCtx.sfa, uri ):
1047cdf0e10cSrcweir            self.provCtx.addPackageByUrl( uri )
1048cdf0e10cSrcweir        else:
1049cdf0e10cSrcweir            # package is no python package ...
1050cdf0e10cSrcweir            log.debug( "insertByName: no python files in " + str( uri ) + ", ignoring" )
1051cdf0e10cSrcweir            raise IllegalArgumentException( uri + " does not contain .py files", self, 1 )
1052cdf0e10cSrcweir        log.debug( "insertByName called " + str( uri ) + " successful" )
1053cdf0e10cSrcweir
1054cdf0e10cSrcweir    def replaceByName( self, name, value ):
1055cdf0e10cSrcweir        log.debug( "replaceByName called " + str( name ) + " " + str( value ))
1056cdf0e10cSrcweir        removeByName( name )
1057cdf0e10cSrcweir        insertByName( name )
1058cdf0e10cSrcweir        log.debug( "replaceByName called" + str( uri ) + " successful" )
1059cdf0e10cSrcweir
1060cdf0e10cSrcweir    def getElementType( self ):
1061cdf0e10cSrcweir        log.debug( "getElementType called" )
1062cdf0e10cSrcweir        return uno.getTypeByName( "void" )
106313cfd8dfSPedro Giffuni
1064cdf0e10cSrcweir    def hasElements( self ):
1065cdf0e10cSrcweir        log.debug( "hasElements got called")
1066cdf0e10cSrcweir        return False
106713cfd8dfSPedro Giffuni
1068cdf0e10cSrcweirg_ImplementationHelper.addImplementation( \
106913cfd8dfSPedro Giffuni        PythonScriptProvider,g_implName, \
1070cdf0e10cSrcweir    ("com.sun.star.script.provider.LanguageScriptProvider",
1071cdf0e10cSrcweir     "com.sun.star.script.provider.ScriptProviderFor"+ LANGUAGENAME,),)
1072cdf0e10cSrcweir
1073cdf0e10cSrcweir
1074cdf0e10cSrcweirlog.debug( "pythonscript finished intializing" )
1075