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:
37b5f289e3SHerbert Dürr    NONE = 0   # production level
38b5f289e3SHerbert Dürr    ERROR = 1  # for script developers
39b5f289e3SHerbert Dürr    DEBUG = 2  # for script framework developers
40b5f289e3SHerbert Dürr
41b5f289e3SHerbert DürrPYSCRIPT_LOG_ENV = "PYSCRIPT_LOG_LEVEL"
42b5f289e3SHerbert DürrPYSCRIPT_LOG_STDOUT_ENV = "PYSCRIPT_LOG_STDOUT"
43cdf0e10cSrcweir
44cdf0e10cSrcweir# Configuration ----------------------------------------------------
45b5f289e3SHerbert DürrLogLevel.use = LogLevel.NONE
46b5f289e3SHerbert Dürrif os.environ.get(PYSCRIPT_LOG_ENV) == "ERROR":
47b5f289e3SHerbert Dürr    LogLevel.use = LogLevel.ERROR
48b5f289e3SHerbert Dürrelif os.environ.get(PYSCRIPT_LOG_ENV) == "DEBUG":
49b5f289e3SHerbert Dürr    LogLevel.use = LogLevel.DEBUG
50b5f289e3SHerbert Dürr
51b5f289e3SHerbert Dürr# True, writes to stdout (difficult on windows)
52b5f289e3SHerbert Dürr# False, writes to user/Scripts/python/log.txt
53b5f289e3SHerbert DürrLOG_STDOUT = os.environ.get(PYSCRIPT_LOG_STDOUT_ENV, "1") != "0"
54b5f289e3SHerbert Dürr
55cdf0e10cSrcweirENABLE_EDIT_DIALOG=False                    # offers a minimal editor for editing.
56cdf0e10cSrcweir#-------------------------------------------------------------------
57cdf0e10cSrcweir
58cdf0e10cSrcweirdef encfile(uni):
59*b4375c20SDamjan Jovanovic    if sys.version_info[0] > 2:
60*b4375c20SDamjan Jovanovic        return uni
61*b4375c20SDamjan Jovanovic    else:
62*b4375c20SDamjan Jovanovic        return uni.encode( sys.getfilesystemencoding())
63cdf0e10cSrcweir
64cdf0e10cSrcweirdef lastException2String():
65cdf0e10cSrcweir    (excType,excInstance,excTraceback) = sys.exc_info()
66cdf0e10cSrcweir    ret = str(excType) + ": "+str(excInstance) + "\n" + \
67cdf0e10cSrcweir          uno._uno_extract_printable_stacktrace( excTraceback )
68cdf0e10cSrcweir    return ret
69cdf0e10cSrcweir
70cdf0e10cSrcweirdef logLevel2String( level ):
71cdf0e10cSrcweir    ret = " NONE"
72cdf0e10cSrcweir    if level == LogLevel.ERROR:
73cdf0e10cSrcweir        ret = "ERROR"
74cdf0e10cSrcweir    elif level >= LogLevel.DEBUG:
75cdf0e10cSrcweir        ret = "DEBUG"
76cdf0e10cSrcweir    return ret
77cdf0e10cSrcweir
78cdf0e10cSrcweirdef getLogTarget():
79cdf0e10cSrcweir    ret = sys.stdout
80cdf0e10cSrcweir    if not LOG_STDOUT:
81cdf0e10cSrcweir        try:
82cdf0e10cSrcweir            pathSubst = uno.getComponentContext().ServiceManager.createInstance(
83cdf0e10cSrcweir                "com.sun.star.util.PathSubstitution" )
84cdf0e10cSrcweir            userInstallation =  pathSubst.getSubstituteVariableValue( "user" )
85cdf0e10cSrcweir            if len( userInstallation ) > 0:
86cdf0e10cSrcweir                systemPath = uno.fileUrlToSystemPath( userInstallation + "/Scripts/python/log.txt" )
87*b4375c20SDamjan Jovanovic                ret = open( systemPath , "a" )
8815745147SPedro Giffuni        except Exception as e:
8915745147SPedro Giffuni            print("Exception during creation of pythonscript logfile: "+ lastException2String() + "\n, delagating log to stdout\n")
90cdf0e10cSrcweir    return ret
9113cfd8dfSPedro Giffuni
92cdf0e10cSrcweirclass Logger(LogLevel):
93cdf0e10cSrcweir    def __init__(self , target ):
94cdf0e10cSrcweir        self.target = target
95cdf0e10cSrcweir
96cdf0e10cSrcweir    def isDebugLevel( self ):
97cdf0e10cSrcweir        return self.use >= self.DEBUG
9813cfd8dfSPedro Giffuni
99cdf0e10cSrcweir    def debug( self, msg ):
100cdf0e10cSrcweir        if self.isDebugLevel():
101cdf0e10cSrcweir            self.log( self.DEBUG, msg )
10213cfd8dfSPedro Giffuni
103cdf0e10cSrcweir    def isErrorLevel( self ):
104cdf0e10cSrcweir        return self.use >= self.ERROR
105cdf0e10cSrcweir
106cdf0e10cSrcweir    def error( self, msg ):
107cdf0e10cSrcweir        if self.isErrorLevel():
108cdf0e10cSrcweir            self.log( self.ERROR, msg )
109cdf0e10cSrcweir
110cdf0e10cSrcweir    def log( self, level, msg ):
111cdf0e10cSrcweir        if self.use >= level:
112cdf0e10cSrcweir            try:
113cdf0e10cSrcweir                self.target.write(
114cdf0e10cSrcweir                    time.asctime() +
115cdf0e10cSrcweir                    " [" +
116cdf0e10cSrcweir                    logLevel2String( level ) +
117cdf0e10cSrcweir                    "] " +
118cdf0e10cSrcweir                    encfile(msg) +
119cdf0e10cSrcweir                    "\n" )
120cdf0e10cSrcweir                self.target.flush()
12115745147SPedro Giffuni            except Exception as e:
12215745147SPedro Giffuni                print("Error during writing to stdout: " +lastException2String() + "\n")
123cdf0e10cSrcweir
124cdf0e10cSrcweirlog = Logger( getLogTarget() )
125cdf0e10cSrcweir
126cdf0e10cSrcweirlog.debug( "pythonscript loading" )
127cdf0e10cSrcweir
128cdf0e10cSrcweir#from com.sun.star.lang import typeOfXServiceInfo, typeOfXTypeProvider
129cdf0e10cSrcweirfrom com.sun.star.uno import RuntimeException
130cdf0e10cSrcweirfrom com.sun.star.lang import XServiceInfo
131cdf0e10cSrcweirfrom com.sun.star.io import IOException
13261c9e2f8SAriel Constenla-Hailefrom com.sun.star.ucb import CommandAbortedException, XCommandEnvironment, XProgressHandler, Command
133cdf0e10cSrcweirfrom com.sun.star.task import XInteractionHandler
13461c9e2f8SAriel Constenla-Hailefrom com.sun.star.beans import XPropertySet, Property
135cdf0e10cSrcweirfrom com.sun.star.container import XNameContainer
136cdf0e10cSrcweirfrom com.sun.star.xml.sax import XDocumentHandler, InputSource
137cdf0e10cSrcweirfrom com.sun.star.uno import Exception as UnoException
138cdf0e10cSrcweirfrom com.sun.star.script import XInvocation
139cdf0e10cSrcweirfrom com.sun.star.awt import XActionListener
140cdf0e10cSrcweir
141cdf0e10cSrcweirfrom com.sun.star.script.provider import XScriptProvider, XScript, XScriptContext, ScriptFrameworkErrorException
142cdf0e10cSrcweirfrom com.sun.star.script.browse import XBrowseNode
143cdf0e10cSrcweirfrom com.sun.star.script.browse.BrowseNodeTypes import SCRIPT, CONTAINER, ROOT
144cdf0e10cSrcweirfrom com.sun.star.util import XModifyListener
145cdf0e10cSrcweir
146cdf0e10cSrcweirLANGUAGENAME = "Python"
147cdf0e10cSrcweirGLOBAL_SCRIPTCONTEXT_NAME = "XSCRIPTCONTEXT"
148cdf0e10cSrcweirCALLABLE_CONTAINER_NAME =  "g_exportedScripts"
149cdf0e10cSrcweir
150cdf0e10cSrcweir# pythonloader looks for a static g_ImplementationHelper variable
151cdf0e10cSrcweirg_ImplementationHelper = unohelper.ImplementationHelper()
152cdf0e10cSrcweirg_implName = "org.openoffice.pyuno.LanguageScriptProviderFor"+LANGUAGENAME
153cdf0e10cSrcweir
154cdf0e10cSrcweir
155cdf0e10cSrcweir
156cdf0e10cSrcweirBLOCK_SIZE = 65536
157cdf0e10cSrcweirdef readTextFromStream( inputStream ):
158cdf0e10cSrcweir    # read the file
159*b4375c20SDamjan Jovanovic    code = uno.ByteSequence( b"" )
160cdf0e10cSrcweir    while True:
161cdf0e10cSrcweir        read,out = inputStream.readBytes( None , BLOCK_SIZE )
162cdf0e10cSrcweir        code = code + out
163cdf0e10cSrcweir        if read < BLOCK_SIZE:
16413cfd8dfSPedro Giffuni            break
165*b4375c20SDamjan Jovanovic    if sys.version_info[0] > 2:
166*b4375c20SDamjan Jovanovic        return str( code.value, 'utf-8' )
167*b4375c20SDamjan Jovanovic    else:
168*b4375c20SDamjan Jovanovic        return code.value
16913cfd8dfSPedro Giffuni
170cdf0e10cSrcweirdef toIniName( str ):
171cdf0e10cSrcweir    # TODO: what is the official way to get to know whether i am on the windows platform ?
172cdf0e10cSrcweir    if( hasattr(sys , "dllhandle") ):
173cdf0e10cSrcweir        return str + ".ini"
174cdf0e10cSrcweir    return str + "rc"
175cdf0e10cSrcweir
176cdf0e10cSrcweir
177cdf0e10cSrcweir""" definition: storageURI is the system dependent, absolute file url, where the script is stored on disk
178cdf0e10cSrcweir                scriptURI is the system independent uri
179cdf0e10cSrcweir"""
180cdf0e10cSrcweirclass MyUriHelper:
181cdf0e10cSrcweir
182cdf0e10cSrcweir    def __init__( self, ctx, location ):
183cdf0e10cSrcweir        self.s_UriMap = \
184910823aeSJürgen Schmidt        { "share" : "vnd.sun.star.expand:${$OOO_BASE_DIR/program/" +  toIniName( "bootstrap") + "::BaseInstallation}/share/Scripts/python" , \
185cdf0e10cSrcweir          "share:uno_packages" : "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE/uno_packages", \
186910823aeSJürgen Schmidt          "user" : "vnd.sun.star.expand:${$OOO_BASE_DIR/program/" + toIniName( "bootstrap") + "::UserInstallation}/user/Scripts/python" , \
18713cfd8dfSPedro Giffuni          "user:uno_packages" : "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/uno_packages" }
188cdf0e10cSrcweir        self.m_uriRefFac = ctx.ServiceManager.createInstanceWithContext("com.sun.star.uri.UriReferenceFactory",ctx)
189cdf0e10cSrcweir        if location.startswith( "vnd.sun.star.tdoc" ):
190cdf0e10cSrcweir            self.m_baseUri = location + "/Scripts/python"
191cdf0e10cSrcweir            self.m_scriptUriLocation = "document"
192cdf0e10cSrcweir        else:
193cdf0e10cSrcweir            self.m_baseUri = expandUri( self.s_UriMap[location] )
194cdf0e10cSrcweir            self.m_scriptUriLocation = location
195735dd73bSPedro Giffuni        log.debug( "initialized urihelper with baseUri="+self.m_baseUri + ",m_scriptUriLocation="+self.m_scriptUriLocation )
19613cfd8dfSPedro Giffuni
197cdf0e10cSrcweir    def getRootStorageURI( self ):
198cdf0e10cSrcweir        return self.m_baseUri
19913cfd8dfSPedro Giffuni
200cdf0e10cSrcweir    def getStorageURI( self, scriptURI ):
201cdf0e10cSrcweir        return self.scriptURI2StorageUri(scriptURI)
202cdf0e10cSrcweir
203cdf0e10cSrcweir    def getScriptURI( self, storageURI ):
204cdf0e10cSrcweir        return self.storageURI2ScriptUri(storageURI)
205cdf0e10cSrcweir
206cdf0e10cSrcweir    def storageURI2ScriptUri( self, storageURI ):
207cdf0e10cSrcweir        if not storageURI.startswith( self.m_baseUri ):
208cdf0e10cSrcweir            message = "pythonscript: storage uri '" + storageURI + "' not in base uri '" + self.m_baseUri + "'"
209735dd73bSPedro Giffuni            log.debug( message )
210cdf0e10cSrcweir            raise RuntimeException( message )
211cdf0e10cSrcweir
212cdf0e10cSrcweir        ret = "vnd.sun.star.script:" + \
213cdf0e10cSrcweir              storageURI[len(self.m_baseUri)+1:].replace("/","|") + \
214cdf0e10cSrcweir              "?language=" + LANGUAGENAME + "&location=" + self.m_scriptUriLocation
215735dd73bSPedro Giffuni        log.debug( "converting storageURI="+storageURI + " to scriptURI=" + ret )
216cdf0e10cSrcweir        return ret
21713cfd8dfSPedro Giffuni
218cdf0e10cSrcweir    def scriptURI2StorageUri( self, scriptURI ):
219cdf0e10cSrcweir        try:
220cdf0e10cSrcweir            myUri = self.m_uriRefFac.parse(scriptURI)
221cdf0e10cSrcweir            ret = self.m_baseUri + "/" + myUri.getName().replace( "|", "/" )
222735dd73bSPedro Giffuni            log.debug( "converting scriptURI="+scriptURI + " to storageURI=" + ret )
223cdf0e10cSrcweir            return ret
22415745147SPedro Giffuni        except UnoException as e:
225cdf0e10cSrcweir            log.error( "error during converting scriptURI="+scriptURI + ": " + e.Message)
226cdf0e10cSrcweir            raise RuntimeException( "pythonscript:scriptURI2StorageUri: " +e.getMessage(), None )
22715745147SPedro Giffuni        except Exception as e:
228cdf0e10cSrcweir            log.error( "error during converting scriptURI="+scriptURI + ": " + str(e))
229cdf0e10cSrcweir            raise RuntimeException( "pythonscript:scriptURI2StorageUri: " + str(e), None )
23013cfd8dfSPedro Giffuni
231cdf0e10cSrcweir
232cdf0e10cSrcweirclass ModuleEntry:
233cdf0e10cSrcweir    def __init__( self, lastRead, module ):
234cdf0e10cSrcweir        self.lastRead = lastRead
235cdf0e10cSrcweir        self.module = module
236cdf0e10cSrcweir
237cdf0e10cSrcweirdef hasChanged( oldDate, newDate ):
238cdf0e10cSrcweir    return newDate.Year > oldDate.Year or \
239cdf0e10cSrcweir           newDate.Month > oldDate.Month or \
240cdf0e10cSrcweir           newDate.Day > oldDate.Day or \
241cdf0e10cSrcweir           newDate.Hours > oldDate.Hours or \
242cdf0e10cSrcweir           newDate.Minutes > oldDate.Minutes or \
243cdf0e10cSrcweir           newDate.Seconds > oldDate.Seconds or \
244cdf0e10cSrcweir           newDate.HundredthSeconds > oldDate.HundredthSeconds
245cdf0e10cSrcweir
246cdf0e10cSrcweirdef ensureSourceState( code ):
247cdf0e10cSrcweir    if not code.endswith( "\n" ):
248cdf0e10cSrcweir        code = code + "\n"
249cdf0e10cSrcweir    code = code.replace( "\r", "" )
250cdf0e10cSrcweir    return code
251cdf0e10cSrcweir
252cdf0e10cSrcweir
253cdf0e10cSrcweirdef checkForPythonPathBesideScript( url ):
254cdf0e10cSrcweir    if url.startswith( "file:" ):
255cdf0e10cSrcweir        path = unohelper.fileUrlToSystemPath( url+"/pythonpath.zip" );
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 )
260cdf0e10cSrcweir
261cdf0e10cSrcweir        path = unohelper.fileUrlToSystemPath( url+"/pythonpath" );
262cdf0e10cSrcweir        log.log( LogLevel.DEBUG,  "checking for existence of " + path )
263cdf0e10cSrcweir        if 1 == os.access( encfile(path), os.F_OK) and not path in sys.path:
264cdf0e10cSrcweir            log.log( LogLevel.DEBUG, "adding " + path + " to sys.path" )
265cdf0e10cSrcweir            sys.path.append( path )
26613cfd8dfSPedro Giffuni
26713cfd8dfSPedro Giffuni
268cdf0e10cSrcweirclass ScriptContext(unohelper.Base):
26961c9e2f8SAriel Constenla-Haile    def __init__( self, ctx, doc, inv ):
270cdf0e10cSrcweir        self.ctx = ctx
271cdf0e10cSrcweir        self.doc = doc
27261c9e2f8SAriel Constenla-Haile        self.inv = inv
27313cfd8dfSPedro Giffuni
274cdf0e10cSrcweir   # XScriptContext
275cdf0e10cSrcweir    def getDocument(self):
27661c9e2f8SAriel Constenla-Haile        if self.doc:
27761c9e2f8SAriel Constenla-Haile            return self.doc
278cdf0e10cSrcweir        return self.getDesktop().getCurrentComponent()
279cdf0e10cSrcweir
280cdf0e10cSrcweir    def getDesktop(self):
281cdf0e10cSrcweir        return self.ctx.ServiceManager.createInstanceWithContext(
282cdf0e10cSrcweir            "com.sun.star.frame.Desktop", self.ctx )
283cdf0e10cSrcweir
284cdf0e10cSrcweir    def getComponentContext(self):
285cdf0e10cSrcweir        return self.ctx
286cdf0e10cSrcweir
28761c9e2f8SAriel Constenla-Haile    def getInvocationContext(self):
28861c9e2f8SAriel Constenla-Haile        return self.inv
28961c9e2f8SAriel Constenla-Haile
290cdf0e10cSrcweir#----------------------------------
291cdf0e10cSrcweir# Global Module Administration
292cdf0e10cSrcweir# does not fit together with script
293cdf0e10cSrcweir# engine lifetime management
294cdf0e10cSrcweir#----------------------------------
295cdf0e10cSrcweir#g_scriptContext = ScriptContext( uno.getComponentContext(), None )
296cdf0e10cSrcweir#g_modules = {}
297cdf0e10cSrcweir#def getModuleByUrl( url, sfa ):
298cdf0e10cSrcweir#    entry =  g_modules.get(url)
299cdf0e10cSrcweir#    load = True
300cdf0e10cSrcweir#    lastRead = sfa.getDateTimeModified( url )
301cdf0e10cSrcweir#    if entry:
302cdf0e10cSrcweir#        if hasChanged( entry.lastRead, lastRead ):
303735dd73bSPedro Giffuni#            log.debug("file " + url + " has changed, reloading")
304cdf0e10cSrcweir#        else:
305cdf0e10cSrcweir#            load = False
30613cfd8dfSPedro Giffuni#
307cdf0e10cSrcweir#    if load:
308735dd73bSPedro Giffuni#        log.debug( "opening >" + url + "<" )
309cdf0e10cSrcweir#
310cdf0e10cSrcweir#        code = readTextFromStream( sfa.openFileRead( url ) )
31113cfd8dfSPedro Giffuni
312cdf0e10cSrcweir        # execute the module
313cdf0e10cSrcweir#        entry = ModuleEntry( lastRead, imp.new_module("ooo_script_framework") )
314cdf0e10cSrcweir#        entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = g_scriptContext
315cdf0e10cSrcweir#        entry.module.__file__ = url
316cdf0e10cSrcweir#        exec code in entry.module.__dict__
317cdf0e10cSrcweir#        g_modules[ url ] = entry
318735dd73bSPedro Giffuni#        log.debug( "mapped " + url + " to " + str( entry.module ) )
319cdf0e10cSrcweir#    return entry.module
320cdf0e10cSrcweir
321cdf0e10cSrcweirclass ProviderContext:
322cdf0e10cSrcweir    def __init__( self, storageType, sfa, uriHelper, scriptContext ):
323cdf0e10cSrcweir        self.storageType = storageType
324cdf0e10cSrcweir        self.sfa = sfa
325cdf0e10cSrcweir        self.uriHelper = uriHelper
326cdf0e10cSrcweir        self.scriptContext = scriptContext
327cdf0e10cSrcweir        self.modules = {}
328cdf0e10cSrcweir        self.rootUrl = None
329cdf0e10cSrcweir        self.mapPackageName2Path = None
330cdf0e10cSrcweir
331cdf0e10cSrcweir    def getTransientPartFromUrl( self, url ):
332cdf0e10cSrcweir        rest = url.replace( self.rootUrl , "",1 ).replace( "/","",1)
333cdf0e10cSrcweir        return rest[0:rest.find("/")]
33413cfd8dfSPedro Giffuni
335cdf0e10cSrcweir    def getPackageNameFromUrl( self, url ):
336cdf0e10cSrcweir        rest = url.replace( self.rootUrl , "",1 ).replace( "/","",1)
337cdf0e10cSrcweir        start = rest.find("/") +1
338cdf0e10cSrcweir        return rest[start:rest.find("/",start)]
33913cfd8dfSPedro Giffuni
34013cfd8dfSPedro Giffuni
341cdf0e10cSrcweir    def removePackageByUrl( self, url ):
34215745147SPedro Giffuni        items = list(self.mapPackageName2Path.items())
343cdf0e10cSrcweir        for i in items:
344cdf0e10cSrcweir            if url in i[1].pathes:
345cdf0e10cSrcweir                self.mapPackageName2Path.pop(i[0])
346cdf0e10cSrcweir                break
347cdf0e10cSrcweir
348cdf0e10cSrcweir    def addPackageByUrl( self, url ):
349cdf0e10cSrcweir        packageName = self.getPackageNameFromUrl( url )
350cdf0e10cSrcweir        transientPart = self.getTransientPartFromUrl( url )
351735dd73bSPedro Giffuni        log.debug( "addPackageByUrl : " + packageName + ", " + transientPart + "("+url+")" + ", rootUrl="+self.rootUrl )
35215745147SPedro Giffuni        if packageName in self.mapPackageName2Path:
353cdf0e10cSrcweir            package = self.mapPackageName2Path[ packageName ]
354cdf0e10cSrcweir            package.pathes = package.pathes + (url, )
355cdf0e10cSrcweir        else:
356cdf0e10cSrcweir            package = Package( (url,), transientPart)
357cdf0e10cSrcweir            self.mapPackageName2Path[ packageName ] = package
35813cfd8dfSPedro Giffuni
359cdf0e10cSrcweir    def isUrlInPackage( self, url ):
36015745147SPedro Giffuni        values = list(self.mapPackageName2Path.values())
361cdf0e10cSrcweir        for i in values:
36213cfd8dfSPedro Giffuni#           print "checking " + url + " in " + str(i.pathes)
363cdf0e10cSrcweir            if url in i.pathes:
36413cfd8dfSPedro Giffuni                return True
365cdf0e10cSrcweir#        print "false"
366cdf0e10cSrcweir        return False
36713cfd8dfSPedro Giffuni
368cdf0e10cSrcweir    def setPackageAttributes( self, mapPackageName2Path, rootUrl ):
369cdf0e10cSrcweir        self.mapPackageName2Path = mapPackageName2Path
370cdf0e10cSrcweir        self.rootUrl = rootUrl
37113cfd8dfSPedro Giffuni
372cdf0e10cSrcweir    def getPersistentUrlFromStorageUrl( self, url ):
373cdf0e10cSrcweir        # package name is the second directory
374cdf0e10cSrcweir        ret = url
375cdf0e10cSrcweir        if self.rootUrl:
376cdf0e10cSrcweir            pos = len( self.rootUrl) +1
377cdf0e10cSrcweir            ret = url[0:pos]+url[url.find("/",pos)+1:len(url)]
378735dd73bSPedro Giffuni        log.debug( "getPersistentUrlFromStorageUrl " + url +  " -> "+ ret)
379cdf0e10cSrcweir        return ret
380cdf0e10cSrcweir
381cdf0e10cSrcweir    def getStorageUrlFromPersistentUrl( self, url):
382cdf0e10cSrcweir        ret = url
383cdf0e10cSrcweir        if self.rootUrl:
384cdf0e10cSrcweir            pos = len(self.rootUrl)+1
385cdf0e10cSrcweir            packageName = url[pos:url.find("/",pos+1)]
386cdf0e10cSrcweir            package = self.mapPackageName2Path[ packageName ]
387cdf0e10cSrcweir            ret = url[0:pos]+ package.transientPathElement + "/" + url[pos:len(url)]
388735dd73bSPedro Giffuni        log.debug( "getStorageUrlFromPersistentUrl " + url + " -> "+ ret)
389cdf0e10cSrcweir        return ret
390cdf0e10cSrcweir
391cdf0e10cSrcweir    def getFuncsByUrl( self, url ):
392cdf0e10cSrcweir        src = readTextFromStream( self.sfa.openFileRead( url ) )
393cdf0e10cSrcweir        checkForPythonPathBesideScript( url[0:url.rfind('/')] )
394cdf0e10cSrcweir        src = ensureSourceState( src )
395cdf0e10cSrcweir
396cdf0e10cSrcweir        allFuncs = []
397cdf0e10cSrcweir        g_exportedScripts = []
398cdf0e10cSrcweir
39913cfd8dfSPedro Giffuni        a = ast.parse(src, url)
40013cfd8dfSPedro Giffuni
40113cfd8dfSPedro Giffuni        if isinstance(a, ast.Module):
40213cfd8dfSPedro Giffuni            for node in a.body:
40313cfd8dfSPedro Giffuni                if isinstance(node, ast.FunctionDef):
40413cfd8dfSPedro Giffuni                    allFuncs.append(node.name)
40513cfd8dfSPedro Giffuni                elif isinstance(node, ast.Assign):
40613cfd8dfSPedro Giffuni                    is_exported = False
40713cfd8dfSPedro Giffuni                    for subnode in node.targets:
40813cfd8dfSPedro Giffuni                        if isinstance(subnode, ast.Name) and \
40913cfd8dfSPedro Giffuni                            subnode.id == "g_exportedScripts":
41013cfd8dfSPedro Giffuni                            is_exported = True
41113cfd8dfSPedro Giffuni                            break
41213cfd8dfSPedro Giffuni                    if is_exported:
41313cfd8dfSPedro Giffuni                        value_node = node.value
41413cfd8dfSPedro Giffuni                        if isinstance(value_node, ast.List) or \
41513cfd8dfSPedro Giffuni                            isinstance(value_node, ast.Tuple):
41613cfd8dfSPedro Giffuni                            for elt in value_node.elts:
41713cfd8dfSPedro Giffuni                                if isinstance(elt, ast.Str):
41813cfd8dfSPedro Giffuni                                    g_exportedScripts.append(elt.s)
41913cfd8dfSPedro Giffuni                                elif isinstance(elt, ast.Name):
42013cfd8dfSPedro Giffuni                                    g_exportedScripts.append(elt.id)
42113cfd8dfSPedro Giffuni                        elif isinstance(value_node, ast.Str):
42213cfd8dfSPedro Giffuni                            g_exportedScripts.append(value_node.s)
42313cfd8dfSPedro Giffuni                        elif isinstance(value_node, ast.Name):
42413cfd8dfSPedro Giffuni                            g_exportedScripts.append(value_node.id)
42513cfd8dfSPedro Giffuni                        return g_exportedScripts
426cdf0e10cSrcweir        return allFuncs
42713cfd8dfSPedro Giffuni
428cdf0e10cSrcweir    def getModuleByUrl( self, url ):
429cdf0e10cSrcweir        entry =  self.modules.get(url)
430cdf0e10cSrcweir        load = True
431cdf0e10cSrcweir        lastRead = self.sfa.getDateTimeModified( url )
432cdf0e10cSrcweir        if entry:
433cdf0e10cSrcweir            if hasChanged( entry.lastRead, lastRead ):
434735dd73bSPedro Giffuni                log.debug( "file " + url + " has changed, reloading" )
435cdf0e10cSrcweir            else:
436cdf0e10cSrcweir                load = False
43713cfd8dfSPedro Giffuni
438cdf0e10cSrcweir        if load:
439735dd73bSPedro Giffuni            log.debug( "opening >" + url + "<" )
44013cfd8dfSPedro Giffuni
441cdf0e10cSrcweir            src = readTextFromStream( self.sfa.openFileRead( url ) )
442cdf0e10cSrcweir            checkForPythonPathBesideScript( url[0:url.rfind('/')] )
44313cfd8dfSPedro Giffuni            src = ensureSourceState( src )
44413cfd8dfSPedro Giffuni
445cdf0e10cSrcweir            # execute the module
446cdf0e10cSrcweir            entry = ModuleEntry( lastRead, imp.new_module("ooo_script_framework") )
447cdf0e10cSrcweir            entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.scriptContext
448cdf0e10cSrcweir
449cdf0e10cSrcweir            code = None
450cdf0e10cSrcweir            if url.startswith( "file:" ):
451cdf0e10cSrcweir                code = compile( src, encfile(uno.fileUrlToSystemPath( url ) ), "exec" )
452cdf0e10cSrcweir            else:
453cdf0e10cSrcweir                code = compile( src, url, "exec" )
45415745147SPedro Giffuni            exec(code, entry.module.__dict__)
455cdf0e10cSrcweir            entry.module.__file__ = url
456cdf0e10cSrcweir            self.modules[ url ] = entry
457735dd73bSPedro Giffuni            log.debug( "mapped " + url + " to " + str( entry.module ) )
458cdf0e10cSrcweir        return  entry.module
45913cfd8dfSPedro Giffuni
460cdf0e10cSrcweir#--------------------------------------------------
461cdf0e10cSrcweirdef isScript( candidate ):
462cdf0e10cSrcweir    ret = False
463cdf0e10cSrcweir    if isinstance( candidate, type(isScript) ):
464cdf0e10cSrcweir        ret = True
465cdf0e10cSrcweir    return ret
46613cfd8dfSPedro Giffuni
467cdf0e10cSrcweir#-------------------------------------------------------
468cdf0e10cSrcweirclass ScriptBrowseNode( unohelper.Base, XBrowseNode , XPropertySet, XInvocation, XActionListener ):
469cdf0e10cSrcweir    def __init__( self, provCtx, uri, fileName, funcName ):
470cdf0e10cSrcweir        self.fileName = fileName
471cdf0e10cSrcweir        self.funcName = funcName
472cdf0e10cSrcweir        self.provCtx = provCtx
473cdf0e10cSrcweir        self.uri = uri
47413cfd8dfSPedro Giffuni
475cdf0e10cSrcweir    def getName( self ):
476cdf0e10cSrcweir        return self.funcName
477cdf0e10cSrcweir
478cdf0e10cSrcweir    def getChildNodes(self):
479cdf0e10cSrcweir        return ()
480cdf0e10cSrcweir
481cdf0e10cSrcweir    def hasChildNodes(self):
482cdf0e10cSrcweir        return False
48313cfd8dfSPedro Giffuni
484cdf0e10cSrcweir    def getType( self):
485cdf0e10cSrcweir        return SCRIPT
486cdf0e10cSrcweir
487cdf0e10cSrcweir    def getPropertyValue( self, name ):
488cdf0e10cSrcweir        ret = None
489cdf0e10cSrcweir        try:
490cdf0e10cSrcweir            if name == "URI":
491cdf0e10cSrcweir                ret = self.provCtx.uriHelper.getScriptURI(
492cdf0e10cSrcweir                    self.provCtx.getPersistentUrlFromStorageUrl( self.uri + "$" + self.funcName ) )
493cdf0e10cSrcweir            elif name == "Editable" and ENABLE_EDIT_DIALOG:
494cdf0e10cSrcweir                ret = not self.provCtx.sfa.isReadOnly( self.uri )
49513cfd8dfSPedro Giffuni
496735dd73bSPedro Giffuni            log.debug( "ScriptBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) )
49715745147SPedro Giffuni        except Exception as e:
498cdf0e10cSrcweir            log.error( "ScriptBrowseNode.getPropertyValue error " + lastException2String())
499cdf0e10cSrcweir            raise
50013cfd8dfSPedro Giffuni
501cdf0e10cSrcweir        return ret
502cdf0e10cSrcweir    def setPropertyValue( self, name, value ):
503735dd73bSPedro Giffuni        log.debug( "ScriptBrowseNode.setPropertyValue called " + name + "=" +str(value ) )
504cdf0e10cSrcweir    def getPropertySetInfo( self ):
505735dd73bSPedro Giffuni        log.debug( "ScriptBrowseNode.getPropertySetInfo called "  )
506cdf0e10cSrcweir        return None
50713cfd8dfSPedro Giffuni
508cdf0e10cSrcweir    def getIntrospection( self ):
509cdf0e10cSrcweir        return None
510cdf0e10cSrcweir
511cdf0e10cSrcweir    def invoke( self, name, params, outparamindex, outparams ):
512cdf0e10cSrcweir        if name == "Editable":
513cdf0e10cSrcweir            servicename = "com.sun.star.awt.DialogProvider"
514cdf0e10cSrcweir            ctx = self.provCtx.scriptContext.getComponentContext()
515cdf0e10cSrcweir            dlgprov = ctx.ServiceManager.createInstanceWithContext(
516cdf0e10cSrcweir                servicename, ctx )
517cdf0e10cSrcweir
518cdf0e10cSrcweir            self.editor = dlgprov.createDialog(
519cdf0e10cSrcweir                "vnd.sun.star.script:" +
520cdf0e10cSrcweir                "ScriptBindingLibrary.MacroEditor?location=application")
521cdf0e10cSrcweir
522cdf0e10cSrcweir            code = readTextFromStream(self.provCtx.sfa.openFileRead(self.uri))
523cdf0e10cSrcweir            code = ensureSourceState( code )
524cdf0e10cSrcweir            self.editor.getControl("EditorTextField").setText(code)
525cdf0e10cSrcweir
526cdf0e10cSrcweir            self.editor.getControl("RunButton").setActionCommand("Run")
527cdf0e10cSrcweir            self.editor.getControl("RunButton").addActionListener(self)
528cdf0e10cSrcweir            self.editor.getControl("SaveButton").setActionCommand("Save")
529cdf0e10cSrcweir            self.editor.getControl("SaveButton").addActionListener(self)
530cdf0e10cSrcweir
531cdf0e10cSrcweir            self.editor.execute()
532cdf0e10cSrcweir
533cdf0e10cSrcweir        return None
534cdf0e10cSrcweir
535cdf0e10cSrcweir    def actionPerformed( self, event ):
536cdf0e10cSrcweir        try:
537cdf0e10cSrcweir            if event.ActionCommand == "Run":
538cdf0e10cSrcweir                code = self.editor.getControl("EditorTextField").getText()
539cdf0e10cSrcweir                code = ensureSourceState( code )
540cdf0e10cSrcweir                mod = imp.new_module("ooo_script_framework")
541cdf0e10cSrcweir                mod.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.provCtx.scriptContext
54215745147SPedro Giffuni                exec(code, mod.__dict__)
543cdf0e10cSrcweir                values = mod.__dict__.get( CALLABLE_CONTAINER_NAME , None )
544cdf0e10cSrcweir                if not values:
54515745147SPedro Giffuni                    values = list(mod.__dict__.values())
54613cfd8dfSPedro Giffuni
547cdf0e10cSrcweir                for i in values:
548cdf0e10cSrcweir                    if isScript( i ):
549cdf0e10cSrcweir                        i()
550cdf0e10cSrcweir                        break
55113cfd8dfSPedro Giffuni
552cdf0e10cSrcweir            elif event.ActionCommand == "Save":
553cdf0e10cSrcweir                toWrite = uno.ByteSequence(
554cdf0e10cSrcweir                    str(
555cdf0e10cSrcweir                    self.editor.getControl("EditorTextField").getText().encode(
556cdf0e10cSrcweir                    sys.getdefaultencoding())) )
557cdf0e10cSrcweir                copyUrl = self.uri + ".orig"
558cdf0e10cSrcweir                self.provCtx.sfa.move( self.uri, copyUrl )
559cdf0e10cSrcweir                out = self.provCtx.sfa.openFileWrite( self.uri )
560cdf0e10cSrcweir                out.writeBytes( toWrite )
561cdf0e10cSrcweir                out.close()
562cdf0e10cSrcweir                self.provCtx.sfa.kill( copyUrl )
563735dd73bSPedro Giffuni#                log.debug("Save is not implemented yet")
564cdf0e10cSrcweir#                text = self.editor.getControl("EditorTextField").getText()
565735dd73bSPedro Giffuni#                log.debug("Would save: " + text)
56615745147SPedro Giffuni        except Exception as e:
567cdf0e10cSrcweir            # TODO: add an error box here !
568cdf0e10cSrcweir            log.error( lastException2String() )
56913cfd8dfSPedro Giffuni
570cdf0e10cSrcweir
571cdf0e10cSrcweir    def setValue( self, name, value ):
572cdf0e10cSrcweir        return None
573cdf0e10cSrcweir
574cdf0e10cSrcweir    def getValue( self, name ):
575cdf0e10cSrcweir        return None
576cdf0e10cSrcweir
577cdf0e10cSrcweir    def hasMethod( self, name ):
578cdf0e10cSrcweir        return False
579cdf0e10cSrcweir
580cdf0e10cSrcweir    def hasProperty( self, name ):
581cdf0e10cSrcweir        return False
582cdf0e10cSrcweir
58313cfd8dfSPedro Giffuni
584cdf0e10cSrcweir#-------------------------------------------------------
585cdf0e10cSrcweirclass FileBrowseNode( unohelper.Base, XBrowseNode ):
586cdf0e10cSrcweir    def __init__( self, provCtx, uri , name ):
587cdf0e10cSrcweir        self.provCtx = provCtx
588cdf0e10cSrcweir        self.uri = uri
589cdf0e10cSrcweir        self.name = name
590cdf0e10cSrcweir        self.funcnames = None
59113cfd8dfSPedro Giffuni
592cdf0e10cSrcweir    def getName( self ):
593cdf0e10cSrcweir        return self.name
59413cfd8dfSPedro Giffuni
595cdf0e10cSrcweir    def getChildNodes(self):
596cdf0e10cSrcweir        ret = ()
597cdf0e10cSrcweir        try:
598cdf0e10cSrcweir            self.funcnames = self.provCtx.getFuncsByUrl( self.uri )
59913cfd8dfSPedro Giffuni
600cdf0e10cSrcweir            scriptNodeList = []
601cdf0e10cSrcweir            for i in self.funcnames:
602cdf0e10cSrcweir                scriptNodeList.append(
603cdf0e10cSrcweir                    ScriptBrowseNode(
604cdf0e10cSrcweir                    self.provCtx, self.uri, self.name, i ))
605cdf0e10cSrcweir            ret = tuple( scriptNodeList )
606735dd73bSPedro Giffuni            log.debug( "returning " +str(len(ret)) + " ScriptChildNodes on " + self.uri )
60715745147SPedro Giffuni        except Exception as e:
608cdf0e10cSrcweir            text = lastException2String()
609cdf0e10cSrcweir            log.error( "Error while evaluating " + self.uri + ":" + text )
610cdf0e10cSrcweir            raise
611cdf0e10cSrcweir        return ret
612cdf0e10cSrcweir
613cdf0e10cSrcweir    def hasChildNodes(self):
614cdf0e10cSrcweir        try:
615cdf0e10cSrcweir            return len(self.getChildNodes()) > 0
61615745147SPedro Giffuni        except Exception as e:
617cdf0e10cSrcweir            return False
61813cfd8dfSPedro Giffuni
619cdf0e10cSrcweir    def getType( self):
620cdf0e10cSrcweir        return CONTAINER
621cdf0e10cSrcweir
62213cfd8dfSPedro Giffuni
623cdf0e10cSrcweir
624cdf0e10cSrcweirclass DirBrowseNode( unohelper.Base, XBrowseNode ):
625cdf0e10cSrcweir    def __init__( self, provCtx, name, rootUrl ):
626cdf0e10cSrcweir        self.provCtx = provCtx
627cdf0e10cSrcweir        self.name = name
628cdf0e10cSrcweir        self.rootUrl = rootUrl
629cdf0e10cSrcweir
630cdf0e10cSrcweir    def getName( self ):
631cdf0e10cSrcweir        return self.name
632cdf0e10cSrcweir
633cdf0e10cSrcweir    def getChildNodes( self ):
634cdf0e10cSrcweir        try:
635735dd73bSPedro Giffuni            log.debug( "DirBrowseNode.getChildNodes called for " + self.rootUrl )
636cdf0e10cSrcweir            contents = self.provCtx.sfa.getFolderContents( self.rootUrl, True )
637cdf0e10cSrcweir            browseNodeList = []
638cdf0e10cSrcweir            for i in contents:
639cdf0e10cSrcweir                if i.endswith( ".py" ):
640735dd73bSPedro Giffuni                    log.debug( "adding filenode " + i )
641cdf0e10cSrcweir                    browseNodeList.append(
642cdf0e10cSrcweir                        FileBrowseNode( self.provCtx, i, i[i.rfind("/")+1:len(i)-3] ) )
643cdf0e10cSrcweir                elif self.provCtx.sfa.isFolder( i ) and not i.endswith("/pythonpath"):
644735dd73bSPedro Giffuni                    log.debug( "adding DirBrowseNode " + i )
645cdf0e10cSrcweir                    browseNodeList.append( DirBrowseNode( self.provCtx, i[i.rfind("/")+1:len(i)],i))
646cdf0e10cSrcweir            return tuple( browseNodeList )
64715745147SPedro Giffuni        except Exception as e:
648cdf0e10cSrcweir            text = lastException2String()
649cdf0e10cSrcweir            log.error( "DirBrowseNode error: " + str(e) + " while evaluating " + self.rootUrl)
650cdf0e10cSrcweir            log.error( text)
651cdf0e10cSrcweir            return ()
652cdf0e10cSrcweir
653cdf0e10cSrcweir    def hasChildNodes( self ):
654cdf0e10cSrcweir        return True
655cdf0e10cSrcweir
656cdf0e10cSrcweir    def getType( self ):
657cdf0e10cSrcweir        return CONTAINER
658cdf0e10cSrcweir
659cdf0e10cSrcweir    def getScript( self, uri ):
660cdf0e10cSrcweir        log.debug( "DirBrowseNode getScript " + uri + " invoked" )
661cdf0e10cSrcweir        raise IllegalArgumentException( "DirBrowseNode couldn't instantiate script " + uri , self , 0 )
662cdf0e10cSrcweir
663cdf0e10cSrcweir
664cdf0e10cSrcweirclass ManifestHandler( XDocumentHandler, unohelper.Base ):
665cdf0e10cSrcweir    def __init__( self, rootUrl ):
666cdf0e10cSrcweir        self.rootUrl = rootUrl
66713cfd8dfSPedro Giffuni
668cdf0e10cSrcweir    def startDocument( self ):
669cdf0e10cSrcweir        self.urlList = []
67013cfd8dfSPedro Giffuni
671cdf0e10cSrcweir    def endDocument( self ):
672cdf0e10cSrcweir        pass
67313cfd8dfSPedro Giffuni
674cdf0e10cSrcweir    def startElement( self , name, attlist):
675cdf0e10cSrcweir        if name == "manifest:file-entry":
676cdf0e10cSrcweir            if attlist.getValueByName( "manifest:media-type" ) == "application/vnd.sun.star.framework-script":
677cdf0e10cSrcweir                self.urlList.append(
678cdf0e10cSrcweir                    self.rootUrl + "/" + attlist.getValueByName( "manifest:full-path" ) )
679cdf0e10cSrcweir
680cdf0e10cSrcweir    def endElement( self, name ):
681cdf0e10cSrcweir        pass
682cdf0e10cSrcweir
683cdf0e10cSrcweir    def characters ( self, chars ):
684cdf0e10cSrcweir        pass
685cdf0e10cSrcweir
686cdf0e10cSrcweir    def ignoreableWhitespace( self, chars ):
687cdf0e10cSrcweir        pass
688cdf0e10cSrcweir
689cdf0e10cSrcweir    def setDocumentLocator( self, locator ):
690cdf0e10cSrcweir        pass
691cdf0e10cSrcweir
692cdf0e10cSrcweirdef isPyFileInPath( sfa, path ):
693cdf0e10cSrcweir    ret = False
694cdf0e10cSrcweir    contents = sfa.getFolderContents( path, True )
695cdf0e10cSrcweir    for i in contents:
696cdf0e10cSrcweir        if sfa.isFolder(i):
697cdf0e10cSrcweir            ret = isPyFileInPath(sfa,i)
698cdf0e10cSrcweir        else:
699cdf0e10cSrcweir            if i.endswith(".py"):
700cdf0e10cSrcweir                ret = True
701cdf0e10cSrcweir        if ret:
702cdf0e10cSrcweir            break
703cdf0e10cSrcweir    return ret
704cdf0e10cSrcweir
70513cfd8dfSPedro Giffuni# extracts META-INF directory from
706cdf0e10cSrcweirdef getPathesFromPackage( rootUrl, sfa ):
707cdf0e10cSrcweir    ret = ()
708cdf0e10cSrcweir    try:
70913cfd8dfSPedro Giffuni        fileUrl = rootUrl + "/META-INF/manifest.xml"
710cdf0e10cSrcweir        inputStream = sfa.openFileRead( fileUrl )
711cdf0e10cSrcweir        parser = uno.getComponentContext().ServiceManager.createInstance( "com.sun.star.xml.sax.Parser" )
712cdf0e10cSrcweir        handler = ManifestHandler( rootUrl )
713cdf0e10cSrcweir        parser.setDocumentHandler( handler )
714cdf0e10cSrcweir        parser.parseStream( InputSource( inputStream , "", fileUrl, fileUrl ) )
715cdf0e10cSrcweir        for i in tuple(handler.urlList):
716cdf0e10cSrcweir            if not isPyFileInPath( sfa, i ):
717cdf0e10cSrcweir                handler.urlList.remove(i)
718cdf0e10cSrcweir        ret = tuple( handler.urlList )
71915745147SPedro Giffuni    except UnoException as e:
720cdf0e10cSrcweir        text = lastException2String()
721cdf0e10cSrcweir        log.debug( "getPathesFromPackage " + fileUrl + " Exception: " +text )
722cdf0e10cSrcweir        pass
723cdf0e10cSrcweir    return ret
72413cfd8dfSPedro Giffuni
725cdf0e10cSrcweir
726cdf0e10cSrcweirclass Package:
727cdf0e10cSrcweir    def __init__( self, pathes, transientPathElement ):
728cdf0e10cSrcweir        self.pathes = pathes
729cdf0e10cSrcweir        self.transientPathElement = transientPathElement
730cdf0e10cSrcweir
731cdf0e10cSrcweirclass DummyInteractionHandler( unohelper.Base, XInteractionHandler ):
732cdf0e10cSrcweir    def __init__( self ):
733cdf0e10cSrcweir        pass
734cdf0e10cSrcweir    def handle( self, event):
735735dd73bSPedro Giffuni        log.debug( "pythonscript: DummyInteractionHandler.handle " + str( event ) )
736cdf0e10cSrcweir
737cdf0e10cSrcweirclass DummyProgressHandler( unohelper.Base, XProgressHandler ):
738cdf0e10cSrcweir    def __init__( self ):
739cdf0e10cSrcweir        pass
74013cfd8dfSPedro Giffuni
74113cfd8dfSPedro Giffuni    def push( self,status ):
742735dd73bSPedro Giffuni        log.debug( "pythonscript: DummyProgressHandler.push " + str( status ) )
74313cfd8dfSPedro Giffuni    def update( self,status ):
744735dd73bSPedro Giffuni        log.debug( "pythonscript: DummyProgressHandler.update " + str( status ) )
74513cfd8dfSPedro Giffuni    def pop( self ):
746735dd73bSPedro Giffuni        log.debug( "pythonscript: DummyProgressHandler.push " + str( event ) )
747cdf0e10cSrcweir
748cdf0e10cSrcweirclass CommandEnvironment(unohelper.Base, XCommandEnvironment):
749cdf0e10cSrcweir    def __init__( self ):
750cdf0e10cSrcweir        self.progressHandler = DummyProgressHandler()
751cdf0e10cSrcweir        self.interactionHandler = DummyInteractionHandler()
752cdf0e10cSrcweir    def getInteractionHandler( self ):
753cdf0e10cSrcweir        return self.interactionHandler
754cdf0e10cSrcweir    def getProgressHandler( self ):
755cdf0e10cSrcweir        return self.progressHandler
756cdf0e10cSrcweir
757cdf0e10cSrcweir#maybe useful for debugging purposes
758cdf0e10cSrcweir#class ModifyListener( unohelper.Base, XModifyListener ):
759cdf0e10cSrcweir#    def __init__( self ):
760cdf0e10cSrcweir#        pass
761cdf0e10cSrcweir#    def modified( self, event ):
762735dd73bSPedro Giffuni#        log.debug( "pythonscript: ModifyListener.modified " + str( event ) )
763cdf0e10cSrcweir#    def disposing( self, event ):
764735dd73bSPedro Giffuni#        log.debug( "pythonscript: ModifyListener.disposing " + str( event ) )
76561c9e2f8SAriel Constenla-Haile
76661c9e2f8SAriel Constenla-Hailedef getModelFromDocUrl(ctx, url):
76761c9e2f8SAriel Constenla-Haile    """Get document model from document url."""
76861c9e2f8SAriel Constenla-Haile    doc = None
76961c9e2f8SAriel Constenla-Haile    args = ("Local", "Office")
77061c9e2f8SAriel Constenla-Haile    ucb = ctx.getServiceManager().createInstanceWithArgumentsAndContext(
77161c9e2f8SAriel Constenla-Haile        "com.sun.star.ucb.UniversalContentBroker", args, ctx)
77261c9e2f8SAriel Constenla-Haile    identifier = ucb.createContentIdentifier(url)
77361c9e2f8SAriel Constenla-Haile    content = ucb.queryContent(identifier)
77461c9e2f8SAriel Constenla-Haile    p = Property()
77561c9e2f8SAriel Constenla-Haile    p.Name = "DocumentModel"
77661c9e2f8SAriel Constenla-Haile    p.Handle = -1
77713cfd8dfSPedro Giffuni
77861c9e2f8SAriel Constenla-Haile    c = Command()
77961c9e2f8SAriel Constenla-Haile    c.Handle = -1
78061c9e2f8SAriel Constenla-Haile    c.Name = "getPropertyValues"
78161c9e2f8SAriel Constenla-Haile    c.Argument = uno.Any("[]com.sun.star.beans.Property", (p,))
78213cfd8dfSPedro Giffuni
78361c9e2f8SAriel Constenla-Haile    env = CommandEnvironment()
78461c9e2f8SAriel Constenla-Haile    try:
78561c9e2f8SAriel Constenla-Haile        ret = content.execute(c, 0, env)
78661c9e2f8SAriel Constenla-Haile        doc = ret.getObject(1, None)
78715745147SPedro Giffuni    except Exception as e:
78861c9e2f8SAriel Constenla-Haile        log.isErrorLevel() and log.error("getModelFromDocUrl: %s" % url)
78961c9e2f8SAriel Constenla-Haile    return doc
79061c9e2f8SAriel Constenla-Haile
791cdf0e10cSrcweirdef mapStorageType2PackageContext( storageType ):
792cdf0e10cSrcweir    ret = storageType
793cdf0e10cSrcweir    if( storageType == "share:uno_packages" ):
794cdf0e10cSrcweir        ret = "shared"
795cdf0e10cSrcweir    if( storageType == "user:uno_packages" ):
796cdf0e10cSrcweir        ret = "user"
797cdf0e10cSrcweir    return ret
798cdf0e10cSrcweir
799cdf0e10cSrcweirdef getPackageName2PathMap( sfa, storageType ):
800cdf0e10cSrcweir    ret = {}
801cdf0e10cSrcweir    packageManagerFactory = uno.getComponentContext().getValueByName(
802cdf0e10cSrcweir        "/singletons/com.sun.star.deployment.thePackageManagerFactory" )
803cdf0e10cSrcweir    packageManager = packageManagerFactory.getPackageManager(
804cdf0e10cSrcweir        mapStorageType2PackageContext(storageType))
805cdf0e10cSrcweir#    packageManager.addModifyListener( ModifyListener() )
806735dd73bSPedro Giffuni    log.debug( "pythonscript: getPackageName2PathMap start getDeployedPackages" )
807cdf0e10cSrcweir    packages = packageManager.getDeployedPackages(
808cdf0e10cSrcweir        packageManager.createAbortChannel(), CommandEnvironment( ) )
809735dd73bSPedro Giffuni    log.debug( "pythonscript: getPackageName2PathMap end getDeployedPackages (" + str(len(packages))+")" )
810cdf0e10cSrcweir
811cdf0e10cSrcweir    for i in packages:
812735dd73bSPedro Giffuni        log.debug( "inspecting package " + i.Name + "("+i.Identifier.Value+")" )
813cdf0e10cSrcweir        transientPathElement = penultimateElement( i.URL )
814cdf0e10cSrcweir        j = expandUri( i.URL )
815cdf0e10cSrcweir        pathes = getPathesFromPackage( j, sfa )
816cdf0e10cSrcweir        if len( pathes ) > 0:
817cdf0e10cSrcweir            # map package name to url, we need this later
818cdf0e10cSrcweir            log.isErrorLevel() and log.error( "adding Package " + transientPathElement + " " + str( pathes ) )
819cdf0e10cSrcweir            ret[ lastElement( j ) ] = Package( pathes, transientPathElement )
820cdf0e10cSrcweir    return ret
821cdf0e10cSrcweir
822cdf0e10cSrcweirdef penultimateElement( aStr ):
823cdf0e10cSrcweir    lastSlash = aStr.rindex("/")
824cdf0e10cSrcweir    penultimateSlash = aStr.rindex("/",0,lastSlash-1)
825cdf0e10cSrcweir    return  aStr[ penultimateSlash+1:lastSlash ]
826cdf0e10cSrcweir
827cdf0e10cSrcweirdef lastElement( aStr):
828cdf0e10cSrcweir    return aStr[ aStr.rfind( "/" )+1:len(aStr)]
829cdf0e10cSrcweir
830cdf0e10cSrcweirclass PackageBrowseNode( unohelper.Base, XBrowseNode ):
831cdf0e10cSrcweir    def __init__( self, provCtx, name, rootUrl ):
832cdf0e10cSrcweir        self.provCtx = provCtx
833cdf0e10cSrcweir        self.name = name
834cdf0e10cSrcweir        self.rootUrl = rootUrl
835cdf0e10cSrcweir
836cdf0e10cSrcweir    def getName( self ):
837cdf0e10cSrcweir        return self.name
838cdf0e10cSrcweir
839cdf0e10cSrcweir    def getChildNodes( self ):
84015745147SPedro Giffuni        items = list(self.provCtx.mapPackageName2Path.items())
841cdf0e10cSrcweir        browseNodeList = []
842cdf0e10cSrcweir        for i in items:
843cdf0e10cSrcweir            if len( i[1].pathes ) == 1:
844cdf0e10cSrcweir                browseNodeList.append(
845cdf0e10cSrcweir                    DirBrowseNode( self.provCtx, i[0], i[1].pathes[0] ))
846cdf0e10cSrcweir            else:
847cdf0e10cSrcweir                for j in i[1].pathes:
848cdf0e10cSrcweir                    browseNodeList.append(
849cdf0e10cSrcweir                        DirBrowseNode( self.provCtx, i[0]+"."+lastElement(j), j ) )
850cdf0e10cSrcweir        return tuple( browseNodeList )
851cdf0e10cSrcweir
852cdf0e10cSrcweir    def hasChildNodes( self ):
853cdf0e10cSrcweir        return len( self.mapPackageName2Path ) > 0
854cdf0e10cSrcweir
855cdf0e10cSrcweir    def getType( self ):
856cdf0e10cSrcweir        return CONTAINER
857cdf0e10cSrcweir
858cdf0e10cSrcweir    def getScript( self, uri ):
859cdf0e10cSrcweir        log.debug( "DirBrowseNode getScript " + uri + " invoked" )
860cdf0e10cSrcweir        raise IllegalArgumentException( "PackageBrowseNode couldn't instantiate script " + uri , self , 0 )
861cdf0e10cSrcweir
862cdf0e10cSrcweir
863cdf0e10cSrcweir
864cdf0e10cSrcweir
865cdf0e10cSrcweirclass PythonScript( unohelper.Base, XScript ):
866cdf0e10cSrcweir    def __init__( self, func, mod ):
867cdf0e10cSrcweir        self.func = func
868cdf0e10cSrcweir        self.mod = mod
869cdf0e10cSrcweir    def invoke(self, args, out, outindex ):
870735dd73bSPedro Giffuni        log.debug( "PythonScript.invoke " + str( args ) )
871cdf0e10cSrcweir        try:
872cdf0e10cSrcweir            ret = self.func( *args )
87315745147SPedro Giffuni        except UnoException as e:
874cdf0e10cSrcweir            # UNO Exception continue to fly ...
875cdf0e10cSrcweir            text = lastException2String()
876cdf0e10cSrcweir            complete = "Error during invoking function " + \
877cdf0e10cSrcweir                str(self.func.__name__) + " in module " + \
878cdf0e10cSrcweir                self.mod.__file__ + " (" + text + ")"
879735dd73bSPedro Giffuni            log.debug( complete )
880cdf0e10cSrcweir            # some people may beat me up for modifying the exception text,
881cdf0e10cSrcweir            # but otherwise office just shows
882cdf0e10cSrcweir            # the type name and message text with no more information,
88313cfd8dfSPedro Giffuni            # this is really bad for most users.
884cdf0e10cSrcweir            e.Message = e.Message + " (" + complete + ")"
885cdf0e10cSrcweir            raise
88615745147SPedro Giffuni        except Exception as e:
887cdf0e10cSrcweir            # General python exception are converted to uno RuntimeException
888cdf0e10cSrcweir            text = lastException2String()
889cdf0e10cSrcweir            complete = "Error during invoking function " + \
890cdf0e10cSrcweir                str(self.func.__name__) + " in module " + \
891cdf0e10cSrcweir                self.mod.__file__ + " (" + text + ")"
892735dd73bSPedro Giffuni            log.debug( complete )
893cdf0e10cSrcweir            raise RuntimeException( complete , self )
894735dd73bSPedro Giffuni        log.debug( "PythonScript.invoke ret = " + str( ret ) )
895cdf0e10cSrcweir        return ret, (), ()
896cdf0e10cSrcweir
897cdf0e10cSrcweirdef expandUri(  uri ):
898cdf0e10cSrcweir    if uri.startswith( "vnd.sun.star.expand:" ):
899cdf0e10cSrcweir        uri = uri.replace( "vnd.sun.star.expand:", "",1)
900cdf0e10cSrcweir        uri = uno.getComponentContext().getByName(
901cdf0e10cSrcweir                    "/singletons/com.sun.star.util.theMacroExpander" ).expandMacros( uri )
902cdf0e10cSrcweir    if uri.startswith( "file:" ):
903cdf0e10cSrcweir        uri = uno.absolutize("",uri)   # necessary to get rid of .. in uri
904cdf0e10cSrcweir    return uri
90513cfd8dfSPedro Giffuni
906cdf0e10cSrcweir#--------------------------------------------------------------
907cdf0e10cSrcweirclass PythonScriptProvider( unohelper.Base, XBrowseNode, XScriptProvider, XNameContainer):
908cdf0e10cSrcweir    def __init__( self, ctx, *args ):
909cdf0e10cSrcweir        if log.isDebugLevel():
910cdf0e10cSrcweir            mystr = ""
911cdf0e10cSrcweir            for i in args:
912cdf0e10cSrcweir                if len(mystr) > 0:
913cdf0e10cSrcweir                    mystr = mystr +","
914cdf0e10cSrcweir                mystr = mystr + str(i)
915cdf0e10cSrcweir            log.debug( "Entering PythonScriptProvider.ctor" + mystr )
916cdf0e10cSrcweir
91761c9e2f8SAriel Constenla-Haile        doc = None
91861c9e2f8SAriel Constenla-Haile        inv = None
919cdf0e10cSrcweir        storageType = ""
92061c9e2f8SAriel Constenla-Haile
921cdf0e10cSrcweir        if isinstance(args[0],unicode ):
922cdf0e10cSrcweir            storageType = args[0]
92361c9e2f8SAriel Constenla-Haile            if storageType.startswith( "vnd.sun.star.tdoc" ):
92461c9e2f8SAriel Constenla-Haile                doc = getModelFromDocUrl(ctx, storageType)
925cdf0e10cSrcweir        else:
92661c9e2f8SAriel Constenla-Haile            inv = args[0]
92761c9e2f8SAriel Constenla-Haile            try:
92861c9e2f8SAriel Constenla-Haile                doc = inv.ScriptContainer
92961c9e2f8SAriel Constenla-Haile                content = ctx.getServiceManager().createInstanceWithContext(
93013cfd8dfSPedro Giffuni                    "com.sun.star.frame.TransientDocumentsDocumentContentFactory",
93161c9e2f8SAriel Constenla-Haile                    ctx).createDocumentContent(doc)
93261c9e2f8SAriel Constenla-Haile                storageType = content.getIdentifier().getContentIdentifier()
93315745147SPedro Giffuni            except Exception as e:
93461c9e2f8SAriel Constenla-Haile                text = lastException2String()
93561c9e2f8SAriel Constenla-Haile                log.error( text )
93661c9e2f8SAriel Constenla-Haile
937cdf0e10cSrcweir        isPackage = storageType.endswith( ":uno_packages" )
938cdf0e10cSrcweir
939cdf0e10cSrcweir        try:
940cdf0e10cSrcweir#            urlHelper = ctx.ServiceManager.createInstanceWithArgumentsAndContext(
941cdf0e10cSrcweir#                "com.sun.star.script.provider.ScriptURIHelper", (LANGUAGENAME, storageType), ctx)
942cdf0e10cSrcweir            urlHelper = MyUriHelper( ctx, storageType )
943735dd73bSPedro Giffuni            log.debug( "got urlHelper " + str( urlHelper ) )
94413cfd8dfSPedro Giffuni
945cdf0e10cSrcweir            rootUrl = expandUri( urlHelper.getRootStorageURI() )
946735dd73bSPedro Giffuni            log.debug( storageType + " transformed to " + rootUrl )
947cdf0e10cSrcweir
948cdf0e10cSrcweir            ucbService = "com.sun.star.ucb.SimpleFileAccess"
949cdf0e10cSrcweir            sfa = ctx.ServiceManager.createInstanceWithContext( ucbService, ctx )
950cdf0e10cSrcweir            if not sfa:
951cdf0e10cSrcweir                log.debug("PythonScriptProvider couldn't instantiate " +ucbService)
952cdf0e10cSrcweir                raise RuntimeException(
953cdf0e10cSrcweir                    "PythonScriptProvider couldn't instantiate " +ucbService, self)
954cdf0e10cSrcweir            self.provCtx = ProviderContext(
95561c9e2f8SAriel Constenla-Haile                storageType, sfa, urlHelper, ScriptContext( uno.getComponentContext(), doc, inv ) )
956cdf0e10cSrcweir            if isPackage:
957cdf0e10cSrcweir                mapPackageName2Path = getPackageName2PathMap( sfa, storageType )
958cdf0e10cSrcweir                self.provCtx.setPackageAttributes( mapPackageName2Path , rootUrl )
959cdf0e10cSrcweir                self.dirBrowseNode = PackageBrowseNode( self.provCtx, LANGUAGENAME, rootUrl )
960cdf0e10cSrcweir            else:
961cdf0e10cSrcweir                self.dirBrowseNode = DirBrowseNode( self.provCtx, LANGUAGENAME, rootUrl )
96213cfd8dfSPedro Giffuni
96315745147SPedro Giffuni        except Exception as e:
964cdf0e10cSrcweir            text = lastException2String()
965cdf0e10cSrcweir            log.debug( "PythonScriptProvider could not be instantiated because of : " + text )
966cdf0e10cSrcweir            raise e
967cdf0e10cSrcweir
968cdf0e10cSrcweir    def getName( self ):
969cdf0e10cSrcweir        return self.dirBrowseNode.getName()
970cdf0e10cSrcweir
971cdf0e10cSrcweir    def getChildNodes( self ):
97213cfd8dfSPedro Giffuni        return self.dirBrowseNode.getChildNodes()
973cdf0e10cSrcweir
974cdf0e10cSrcweir    def hasChildNodes( self ):
975cdf0e10cSrcweir        return self.dirBrowseNode.hasChildNodes()
976cdf0e10cSrcweir
977cdf0e10cSrcweir    def getType( self ):
978cdf0e10cSrcweir        return self.dirBrowseNode.getType()
979cdf0e10cSrcweir
980cdf0e10cSrcweir    def getScript( self, uri ):
981cdf0e10cSrcweir        log.debug( "DirBrowseNode getScript " + uri + " invoked" )
98213cfd8dfSPedro Giffuni
983cdf0e10cSrcweir        raise IllegalArgumentException( "DirBrowseNode couldn't instantiate script " + uri , self , 0 )
984cdf0e10cSrcweir
985cdf0e10cSrcweir    def getScript( self, scriptUri ):
986cdf0e10cSrcweir        try:
987735dd73bSPedro Giffuni            log.debug( "getScript " + scriptUri + " invoked")
98813cfd8dfSPedro Giffuni
989cdf0e10cSrcweir            storageUri = self.provCtx.getStorageUrlFromPersistentUrl(
990cdf0e10cSrcweir                self.provCtx.uriHelper.getStorageURI(scriptUri) );
991735dd73bSPedro Giffuni            log.debug( "getScript: storageUri = " + storageUri)
992cdf0e10cSrcweir            fileUri = storageUri[0:storageUri.find( "$" )]
99313cfd8dfSPedro Giffuni            funcName = storageUri[storageUri.find( "$" )+1:len(storageUri)]
99413cfd8dfSPedro Giffuni
995cdf0e10cSrcweir            mod = self.provCtx.getModuleByUrl( fileUri )
996735dd73bSPedro Giffuni            log.debug( " got mod " + str(mod) )
99713cfd8dfSPedro Giffuni
998cdf0e10cSrcweir            func = mod.__dict__[ funcName ]
999cdf0e10cSrcweir
1000735dd73bSPedro Giffuni            log.debug( "got func " + str( func ) )
1001cdf0e10cSrcweir            return PythonScript( func, mod )
100215745147SPedro Giffuni        except Exception as e:
1003cdf0e10cSrcweir            text = lastException2String()
1004cdf0e10cSrcweir            log.error( text )
1005cdf0e10cSrcweir            raise ScriptFrameworkErrorException( text, self, scriptUri, LANGUAGENAME, 0 )
100613cfd8dfSPedro Giffuni
1007cdf0e10cSrcweir
1008cdf0e10cSrcweir    # XServiceInfo
1009cdf0e10cSrcweir    def getSupportedServices( self ):
1010cdf0e10cSrcweir        return g_ImplementationHelper.getSupportedServices(g_implName)
1011cdf0e10cSrcweir
1012cdf0e10cSrcweir    def supportsService( self, ServiceName ):
1013cdf0e10cSrcweir        return g_ImplementationHelper.supportsService( g_implName, ServiceName )
1014cdf0e10cSrcweir
1015cdf0e10cSrcweir    def getImplementationName(self):
1016cdf0e10cSrcweir        return g_implName
1017cdf0e10cSrcweir
1018cdf0e10cSrcweir    def getByName( self, name ):
1019cdf0e10cSrcweir        log.debug( "getByName called" + str( name ))
1020cdf0e10cSrcweir        return None
1021cdf0e10cSrcweir
102213cfd8dfSPedro Giffuni
1023cdf0e10cSrcweir    def getElementNames( self ):
1024cdf0e10cSrcweir        log.debug( "getElementNames called")
1025cdf0e10cSrcweir        return ()
102613cfd8dfSPedro Giffuni
1027cdf0e10cSrcweir    def hasByName( self, name ):
1028cdf0e10cSrcweir        try:
1029cdf0e10cSrcweir            log.debug( "hasByName called " + str( name ))
1030cdf0e10cSrcweir            uri = expandUri(name)
1031cdf0e10cSrcweir            ret = self.provCtx.isUrlInPackage( uri )
1032cdf0e10cSrcweir            log.debug( "hasByName " + uri + " " +str( ret ) )
1033cdf0e10cSrcweir            return ret
103415745147SPedro Giffuni        except Exception as e:
1035cdf0e10cSrcweir            text = lastException2String()
1036cdf0e10cSrcweir            log.debug( "Error in hasByName:" +  text )
1037cdf0e10cSrcweir            return False
1038cdf0e10cSrcweir
1039cdf0e10cSrcweir    def removeByName( self, name ):
1040cdf0e10cSrcweir        log.debug( "removeByName called" + str( name ))
1041cdf0e10cSrcweir        uri = expandUri( name )
1042cdf0e10cSrcweir        if self.provCtx.isUrlInPackage( uri ):
1043cdf0e10cSrcweir            self.provCtx.removePackageByUrl( uri )
1044cdf0e10cSrcweir        else:
1045cdf0e10cSrcweir            log.debug( "removeByName unknown uri " + str( name ) + ", ignoring" )
1046cdf0e10cSrcweir            raise NoSuchElementException( uri + "is not in package" , self )
1047cdf0e10cSrcweir        log.debug( "removeByName called" + str( uri ) + " successful" )
104813cfd8dfSPedro Giffuni
1049cdf0e10cSrcweir    def insertByName( self, name, value ):
1050cdf0e10cSrcweir        log.debug( "insertByName called " + str( name ) + " " + str( value ))
1051cdf0e10cSrcweir        uri = expandUri( name )
1052cdf0e10cSrcweir        if isPyFileInPath( self.provCtx.sfa, uri ):
1053cdf0e10cSrcweir            self.provCtx.addPackageByUrl( uri )
1054cdf0e10cSrcweir        else:
1055cdf0e10cSrcweir            # package is no python package ...
1056cdf0e10cSrcweir            log.debug( "insertByName: no python files in " + str( uri ) + ", ignoring" )
1057cdf0e10cSrcweir            raise IllegalArgumentException( uri + " does not contain .py files", self, 1 )
1058cdf0e10cSrcweir        log.debug( "insertByName called " + str( uri ) + " successful" )
1059cdf0e10cSrcweir
1060cdf0e10cSrcweir    def replaceByName( self, name, value ):
1061cdf0e10cSrcweir        log.debug( "replaceByName called " + str( name ) + " " + str( value ))
1062cdf0e10cSrcweir        removeByName( name )
1063cdf0e10cSrcweir        insertByName( name )
1064cdf0e10cSrcweir        log.debug( "replaceByName called" + str( uri ) + " successful" )
1065cdf0e10cSrcweir
1066cdf0e10cSrcweir    def getElementType( self ):
1067cdf0e10cSrcweir        log.debug( "getElementType called" )
1068cdf0e10cSrcweir        return uno.getTypeByName( "void" )
106913cfd8dfSPedro Giffuni
1070cdf0e10cSrcweir    def hasElements( self ):
1071cdf0e10cSrcweir        log.debug( "hasElements got called")
1072cdf0e10cSrcweir        return False
107313cfd8dfSPedro Giffuni
1074cdf0e10cSrcweirg_ImplementationHelper.addImplementation( \
107513cfd8dfSPedro Giffuni        PythonScriptProvider,g_implName, \
1076cdf0e10cSrcweir    ("com.sun.star.script.provider.LanguageScriptProvider",
1077cdf0e10cSrcweir     "com.sun.star.script.provider.ScriptProviderFor"+ LANGUAGENAME,),)
1078cdf0e10cSrcweir
1079cdf0e10cSrcweir
1080cdf0e10cSrcweirlog.debug( "pythonscript finished intializing" )
1081