1*cdf0e10cSrcweir# XScript implementation for python
2*cdf0e10cSrcweirimport uno
3*cdf0e10cSrcweirimport unohelper
4*cdf0e10cSrcweirimport sys
5*cdf0e10cSrcweirimport os
6*cdf0e10cSrcweirimport imp
7*cdf0e10cSrcweirimport time
8*cdf0e10cSrcweirimport compiler
9*cdf0e10cSrcweir
10*cdf0e10cSrcweirclass LogLevel:
11*cdf0e10cSrcweir    NONE = 0
12*cdf0e10cSrcweir    ERROR = 1
13*cdf0e10cSrcweir    DEBUG = 2
14*cdf0e10cSrcweir
15*cdf0e10cSrcweir# Configuration ----------------------------------------------------
16*cdf0e10cSrcweirLogLevel.use = LogLevel.NONE                # production level
17*cdf0e10cSrcweir#LogLevel.use = LogLevel.ERROR               # for script developers
18*cdf0e10cSrcweir#LogLevel.use = LogLevel.DEBUG               # for script framework developers
19*cdf0e10cSrcweirLOG_STDOUT = True                           # True, writes to stdout (difficult on windows)
20*cdf0e10cSrcweir                                            # False, writes to user/Scripts/python/log.txt
21*cdf0e10cSrcweirENABLE_EDIT_DIALOG=False                    # offers a minimal editor for editing.
22*cdf0e10cSrcweir#-------------------------------------------------------------------
23*cdf0e10cSrcweir
24*cdf0e10cSrcweirdef encfile(uni):
25*cdf0e10cSrcweir    return uni.encode( sys.getfilesystemencoding())
26*cdf0e10cSrcweir
27*cdf0e10cSrcweirdef lastException2String():
28*cdf0e10cSrcweir    (excType,excInstance,excTraceback) = sys.exc_info()
29*cdf0e10cSrcweir    ret = str(excType) + ": "+str(excInstance) + "\n" + \
30*cdf0e10cSrcweir          uno._uno_extract_printable_stacktrace( excTraceback )
31*cdf0e10cSrcweir    return ret
32*cdf0e10cSrcweir
33*cdf0e10cSrcweirdef logLevel2String( level ):
34*cdf0e10cSrcweir    ret = " NONE"
35*cdf0e10cSrcweir    if level == LogLevel.ERROR:
36*cdf0e10cSrcweir        ret = "ERROR"
37*cdf0e10cSrcweir    elif level >= LogLevel.DEBUG:
38*cdf0e10cSrcweir        ret = "DEBUG"
39*cdf0e10cSrcweir    return ret
40*cdf0e10cSrcweir
41*cdf0e10cSrcweirdef getLogTarget():
42*cdf0e10cSrcweir    ret = sys.stdout
43*cdf0e10cSrcweir    if not LOG_STDOUT:
44*cdf0e10cSrcweir        try:
45*cdf0e10cSrcweir            pathSubst = uno.getComponentContext().ServiceManager.createInstance(
46*cdf0e10cSrcweir                "com.sun.star.util.PathSubstitution" )
47*cdf0e10cSrcweir            userInstallation =  pathSubst.getSubstituteVariableValue( "user" )
48*cdf0e10cSrcweir            if len( userInstallation ) > 0:
49*cdf0e10cSrcweir                systemPath = uno.fileUrlToSystemPath( userInstallation + "/Scripts/python/log.txt" )
50*cdf0e10cSrcweir                ret = file( systemPath , "a" )
51*cdf0e10cSrcweir        except Exception,e:
52*cdf0e10cSrcweir            print "Exception during creation of pythonscript logfile: "+ lastException2String() + "\n, delagating log to stdout\n"
53*cdf0e10cSrcweir    return ret
54*cdf0e10cSrcweir
55*cdf0e10cSrcweirclass Logger(LogLevel):
56*cdf0e10cSrcweir    def __init__(self , target ):
57*cdf0e10cSrcweir        self.target = target
58*cdf0e10cSrcweir
59*cdf0e10cSrcweir    def isDebugLevel( self ):
60*cdf0e10cSrcweir        return self.use >= self.DEBUG
61*cdf0e10cSrcweir
62*cdf0e10cSrcweir    def debug( self, msg ):
63*cdf0e10cSrcweir        if self.isDebugLevel():
64*cdf0e10cSrcweir            self.log( self.DEBUG, msg )
65*cdf0e10cSrcweir
66*cdf0e10cSrcweir    def isErrorLevel( self ):
67*cdf0e10cSrcweir        return self.use >= self.ERROR
68*cdf0e10cSrcweir
69*cdf0e10cSrcweir    def error( self, msg ):
70*cdf0e10cSrcweir        if self.isErrorLevel():
71*cdf0e10cSrcweir            self.log( self.ERROR, msg )
72*cdf0e10cSrcweir
73*cdf0e10cSrcweir    def log( self, level, msg ):
74*cdf0e10cSrcweir        if self.use >= level:
75*cdf0e10cSrcweir            try:
76*cdf0e10cSrcweir                self.target.write(
77*cdf0e10cSrcweir                    time.asctime() +
78*cdf0e10cSrcweir                    " [" +
79*cdf0e10cSrcweir                    logLevel2String( level ) +
80*cdf0e10cSrcweir                    "] " +
81*cdf0e10cSrcweir                    encfile(msg) +
82*cdf0e10cSrcweir                    "\n" )
83*cdf0e10cSrcweir                self.target.flush()
84*cdf0e10cSrcweir            except Exception,e:
85*cdf0e10cSrcweir                print "Error during writing to stdout: " +lastException2String() + "\n"
86*cdf0e10cSrcweir
87*cdf0e10cSrcweirlog = Logger( getLogTarget() )
88*cdf0e10cSrcweir
89*cdf0e10cSrcweirlog.debug( "pythonscript loading" )
90*cdf0e10cSrcweir
91*cdf0e10cSrcweir#from com.sun.star.lang import typeOfXServiceInfo, typeOfXTypeProvider
92*cdf0e10cSrcweirfrom com.sun.star.uno import RuntimeException
93*cdf0e10cSrcweirfrom com.sun.star.lang import XServiceInfo
94*cdf0e10cSrcweirfrom com.sun.star.io import IOException
95*cdf0e10cSrcweirfrom com.sun.star.ucb import CommandAbortedException, XCommandEnvironment, XProgressHandler
96*cdf0e10cSrcweirfrom com.sun.star.task import XInteractionHandler
97*cdf0e10cSrcweirfrom com.sun.star.beans import XPropertySet
98*cdf0e10cSrcweirfrom com.sun.star.container import XNameContainer
99*cdf0e10cSrcweirfrom com.sun.star.xml.sax import XDocumentHandler, InputSource
100*cdf0e10cSrcweirfrom com.sun.star.uno import Exception as UnoException
101*cdf0e10cSrcweirfrom com.sun.star.script import XInvocation
102*cdf0e10cSrcweirfrom com.sun.star.awt import XActionListener
103*cdf0e10cSrcweir
104*cdf0e10cSrcweirfrom com.sun.star.script.provider import XScriptProvider, XScript, XScriptContext, ScriptFrameworkErrorException
105*cdf0e10cSrcweirfrom com.sun.star.script.browse import XBrowseNode
106*cdf0e10cSrcweirfrom com.sun.star.script.browse.BrowseNodeTypes import SCRIPT, CONTAINER, ROOT
107*cdf0e10cSrcweirfrom com.sun.star.util import XModifyListener
108*cdf0e10cSrcweir
109*cdf0e10cSrcweirLANGUAGENAME = "Python"
110*cdf0e10cSrcweirGLOBAL_SCRIPTCONTEXT_NAME = "XSCRIPTCONTEXT"
111*cdf0e10cSrcweirCALLABLE_CONTAINER_NAME =  "g_exportedScripts"
112*cdf0e10cSrcweir
113*cdf0e10cSrcweir# pythonloader looks for a static g_ImplementationHelper variable
114*cdf0e10cSrcweirg_ImplementationHelper = unohelper.ImplementationHelper()
115*cdf0e10cSrcweirg_implName = "org.openoffice.pyuno.LanguageScriptProviderFor"+LANGUAGENAME
116*cdf0e10cSrcweir
117*cdf0e10cSrcweir
118*cdf0e10cSrcweir
119*cdf0e10cSrcweirBLOCK_SIZE = 65536
120*cdf0e10cSrcweirdef readTextFromStream( inputStream ):
121*cdf0e10cSrcweir    # read the file
122*cdf0e10cSrcweir    code = uno.ByteSequence( "" )
123*cdf0e10cSrcweir    while True:
124*cdf0e10cSrcweir        read,out = inputStream.readBytes( None , BLOCK_SIZE )
125*cdf0e10cSrcweir        code = code + out
126*cdf0e10cSrcweir        if read < BLOCK_SIZE:
127*cdf0e10cSrcweir           break
128*cdf0e10cSrcweir    return code.value
129*cdf0e10cSrcweir
130*cdf0e10cSrcweirdef toIniName( str ):
131*cdf0e10cSrcweir    # TODO: what is the official way to get to know whether i am on the windows platform ?
132*cdf0e10cSrcweir    if( hasattr(sys , "dllhandle") ):
133*cdf0e10cSrcweir        return str + ".ini"
134*cdf0e10cSrcweir    return str + "rc"
135*cdf0e10cSrcweir
136*cdf0e10cSrcweir
137*cdf0e10cSrcweir""" definition: storageURI is the system dependent, absolute file url, where the script is stored on disk
138*cdf0e10cSrcweir                scriptURI is the system independent uri
139*cdf0e10cSrcweir"""
140*cdf0e10cSrcweirclass MyUriHelper:
141*cdf0e10cSrcweir
142*cdf0e10cSrcweir    def __init__( self, ctx, location ):
143*cdf0e10cSrcweir        self.s_UriMap = \
144*cdf0e10cSrcweir        { "share" : "vnd.sun.star.expand:${$BRAND_BASE_DIR/program/" +  toIniName( "bootstrap") + "::BaseInstallation}/share/Scripts/python" , \
145*cdf0e10cSrcweir          "share:uno_packages" : "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE/uno_packages", \
146*cdf0e10cSrcweir          "user" : "vnd.sun.star.expand:${$BRAND_BASE_DIR/program/" + toIniName( "bootstrap") + "::UserInstallation}/user/Scripts/python" , \
147*cdf0e10cSrcweir          "user:uno_packages" : "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/uno_packages" }
148*cdf0e10cSrcweir        self.m_uriRefFac = ctx.ServiceManager.createInstanceWithContext("com.sun.star.uri.UriReferenceFactory",ctx)
149*cdf0e10cSrcweir        if location.startswith( "vnd.sun.star.tdoc" ):
150*cdf0e10cSrcweir            self.m_baseUri = location + "/Scripts/python"
151*cdf0e10cSrcweir            self.m_scriptUriLocation = "document"
152*cdf0e10cSrcweir        else:
153*cdf0e10cSrcweir            self.m_baseUri = expandUri( self.s_UriMap[location] )
154*cdf0e10cSrcweir            self.m_scriptUriLocation = location
155*cdf0e10cSrcweir        log.isDebugLevel() and log.debug( "initialized urihelper with baseUri="+self.m_baseUri + ",m_scriptUriLocation="+self.m_scriptUriLocation )
156*cdf0e10cSrcweir
157*cdf0e10cSrcweir    def getRootStorageURI( self ):
158*cdf0e10cSrcweir        return self.m_baseUri
159*cdf0e10cSrcweir
160*cdf0e10cSrcweir    def getStorageURI( self, scriptURI ):
161*cdf0e10cSrcweir        return self.scriptURI2StorageUri(scriptURI)
162*cdf0e10cSrcweir
163*cdf0e10cSrcweir    def getScriptURI( self, storageURI ):
164*cdf0e10cSrcweir        return self.storageURI2ScriptUri(storageURI)
165*cdf0e10cSrcweir
166*cdf0e10cSrcweir    def storageURI2ScriptUri( self, storageURI ):
167*cdf0e10cSrcweir        if not storageURI.startswith( self.m_baseUri ):
168*cdf0e10cSrcweir            message = "pythonscript: storage uri '" + storageURI + "' not in base uri '" + self.m_baseUri + "'"
169*cdf0e10cSrcweir            log.isDebugLevel() and log.debug( message )
170*cdf0e10cSrcweir            raise RuntimeException( message )
171*cdf0e10cSrcweir
172*cdf0e10cSrcweir        ret = "vnd.sun.star.script:" + \
173*cdf0e10cSrcweir              storageURI[len(self.m_baseUri)+1:].replace("/","|") + \
174*cdf0e10cSrcweir              "?language=" + LANGUAGENAME + "&location=" + self.m_scriptUriLocation
175*cdf0e10cSrcweir        log.isDebugLevel() and log.debug( "converting storageURI="+storageURI + " to scriptURI=" + ret )
176*cdf0e10cSrcweir        return ret
177*cdf0e10cSrcweir
178*cdf0e10cSrcweir    def scriptURI2StorageUri( self, scriptURI ):
179*cdf0e10cSrcweir        try:
180*cdf0e10cSrcweir            myUri = self.m_uriRefFac.parse(scriptURI)
181*cdf0e10cSrcweir            ret = self.m_baseUri + "/" + myUri.getName().replace( "|", "/" )
182*cdf0e10cSrcweir            log.isDebugLevel() and log.debug( "converting scriptURI="+scriptURI + " to storageURI=" + ret )
183*cdf0e10cSrcweir            return ret
184*cdf0e10cSrcweir        except UnoException, e:
185*cdf0e10cSrcweir            log.error( "error during converting scriptURI="+scriptURI + ": " + e.Message)
186*cdf0e10cSrcweir            raise RuntimeException( "pythonscript:scriptURI2StorageUri: " +e.getMessage(), None )
187*cdf0e10cSrcweir        except Exception, e:
188*cdf0e10cSrcweir            log.error( "error during converting scriptURI="+scriptURI + ": " + str(e))
189*cdf0e10cSrcweir            raise RuntimeException( "pythonscript:scriptURI2StorageUri: " + str(e), None )
190*cdf0e10cSrcweir
191*cdf0e10cSrcweir
192*cdf0e10cSrcweirclass ModuleEntry:
193*cdf0e10cSrcweir    def __init__( self, lastRead, module ):
194*cdf0e10cSrcweir        self.lastRead = lastRead
195*cdf0e10cSrcweir        self.module = module
196*cdf0e10cSrcweir
197*cdf0e10cSrcweirdef hasChanged( oldDate, newDate ):
198*cdf0e10cSrcweir    return newDate.Year > oldDate.Year or \
199*cdf0e10cSrcweir           newDate.Month > oldDate.Month or \
200*cdf0e10cSrcweir           newDate.Day > oldDate.Day or \
201*cdf0e10cSrcweir           newDate.Hours > oldDate.Hours or \
202*cdf0e10cSrcweir           newDate.Minutes > oldDate.Minutes or \
203*cdf0e10cSrcweir           newDate.Seconds > oldDate.Seconds or \
204*cdf0e10cSrcweir           newDate.HundredthSeconds > oldDate.HundredthSeconds
205*cdf0e10cSrcweir
206*cdf0e10cSrcweirdef ensureSourceState( code ):
207*cdf0e10cSrcweir    if not code.endswith( "\n" ):
208*cdf0e10cSrcweir        code = code + "\n"
209*cdf0e10cSrcweir    code = code.replace( "\r", "" )
210*cdf0e10cSrcweir    return code
211*cdf0e10cSrcweir
212*cdf0e10cSrcweir
213*cdf0e10cSrcweirdef checkForPythonPathBesideScript( url ):
214*cdf0e10cSrcweir    if url.startswith( "file:" ):
215*cdf0e10cSrcweir        path = unohelper.fileUrlToSystemPath( url+"/pythonpath.zip" );
216*cdf0e10cSrcweir        log.log( LogLevel.DEBUG,  "checking for existence of " + path )
217*cdf0e10cSrcweir        if 1 == os.access( encfile(path), os.F_OK) and not path in sys.path:
218*cdf0e10cSrcweir            log.log( LogLevel.DEBUG, "adding " + path + " to sys.path" )
219*cdf0e10cSrcweir            sys.path.append( path )
220*cdf0e10cSrcweir
221*cdf0e10cSrcweir        path = unohelper.fileUrlToSystemPath( url+"/pythonpath" );
222*cdf0e10cSrcweir        log.log( LogLevel.DEBUG,  "checking for existence of " + path )
223*cdf0e10cSrcweir        if 1 == os.access( encfile(path), os.F_OK) and not path in sys.path:
224*cdf0e10cSrcweir            log.log( LogLevel.DEBUG, "adding " + path + " to sys.path" )
225*cdf0e10cSrcweir            sys.path.append( path )
226*cdf0e10cSrcweir
227*cdf0e10cSrcweir
228*cdf0e10cSrcweirclass ScriptContext(unohelper.Base):
229*cdf0e10cSrcweir    def __init__( self, ctx, doc ):
230*cdf0e10cSrcweir        self.ctx = ctx
231*cdf0e10cSrcweir        self.doc = doc
232*cdf0e10cSrcweir
233*cdf0e10cSrcweir   # XScriptContext
234*cdf0e10cSrcweir    def getDocument(self):
235*cdf0e10cSrcweir        return self.getDesktop().getCurrentComponent()
236*cdf0e10cSrcweir
237*cdf0e10cSrcweir    def getDesktop(self):
238*cdf0e10cSrcweir        return self.ctx.ServiceManager.createInstanceWithContext(
239*cdf0e10cSrcweir            "com.sun.star.frame.Desktop", self.ctx )
240*cdf0e10cSrcweir
241*cdf0e10cSrcweir    def getComponentContext(self):
242*cdf0e10cSrcweir        return self.ctx
243*cdf0e10cSrcweir
244*cdf0e10cSrcweir#----------------------------------
245*cdf0e10cSrcweir# Global Module Administration
246*cdf0e10cSrcweir# does not fit together with script
247*cdf0e10cSrcweir# engine lifetime management
248*cdf0e10cSrcweir#----------------------------------
249*cdf0e10cSrcweir#g_scriptContext = ScriptContext( uno.getComponentContext(), None )
250*cdf0e10cSrcweir#g_modules = {}
251*cdf0e10cSrcweir#def getModuleByUrl( url, sfa ):
252*cdf0e10cSrcweir#    entry =  g_modules.get(url)
253*cdf0e10cSrcweir#    load = True
254*cdf0e10cSrcweir#    lastRead = sfa.getDateTimeModified( url )
255*cdf0e10cSrcweir#    if entry:
256*cdf0e10cSrcweir#        if hasChanged( entry.lastRead, lastRead ):
257*cdf0e10cSrcweir#            log.isDebugLevel() and log.debug("file " + url + " has changed, reloading")
258*cdf0e10cSrcweir#        else:
259*cdf0e10cSrcweir#            load = False
260*cdf0e10cSrcweir#
261*cdf0e10cSrcweir#    if load:
262*cdf0e10cSrcweir#        log.isDebugLevel() and log.debug( "opening >" + url + "<" )
263*cdf0e10cSrcweir#
264*cdf0e10cSrcweir#        code = readTextFromStream( sfa.openFileRead( url ) )
265*cdf0e10cSrcweir
266*cdf0e10cSrcweir        # execute the module
267*cdf0e10cSrcweir#        entry = ModuleEntry( lastRead, imp.new_module("ooo_script_framework") )
268*cdf0e10cSrcweir#        entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = g_scriptContext
269*cdf0e10cSrcweir#        entry.module.__file__ = url
270*cdf0e10cSrcweir#        exec code in entry.module.__dict__
271*cdf0e10cSrcweir#        g_modules[ url ] = entry
272*cdf0e10cSrcweir#        log.isDebugLevel() and log.debug( "mapped " + url + " to " + str( entry.module ) )
273*cdf0e10cSrcweir#    return entry.module
274*cdf0e10cSrcweir
275*cdf0e10cSrcweirclass ProviderContext:
276*cdf0e10cSrcweir    def __init__( self, storageType, sfa, uriHelper, scriptContext ):
277*cdf0e10cSrcweir        self.storageType = storageType
278*cdf0e10cSrcweir        self.sfa = sfa
279*cdf0e10cSrcweir        self.uriHelper = uriHelper
280*cdf0e10cSrcweir        self.scriptContext = scriptContext
281*cdf0e10cSrcweir        self.modules = {}
282*cdf0e10cSrcweir        self.rootUrl = None
283*cdf0e10cSrcweir        self.mapPackageName2Path = None
284*cdf0e10cSrcweir
285*cdf0e10cSrcweir    def getTransientPartFromUrl( self, url ):
286*cdf0e10cSrcweir        rest = url.replace( self.rootUrl , "",1 ).replace( "/","",1)
287*cdf0e10cSrcweir        return rest[0:rest.find("/")]
288*cdf0e10cSrcweir
289*cdf0e10cSrcweir    def getPackageNameFromUrl( self, url ):
290*cdf0e10cSrcweir        rest = url.replace( self.rootUrl , "",1 ).replace( "/","",1)
291*cdf0e10cSrcweir        start = rest.find("/") +1
292*cdf0e10cSrcweir        return rest[start:rest.find("/",start)]
293*cdf0e10cSrcweir
294*cdf0e10cSrcweir
295*cdf0e10cSrcweir    def removePackageByUrl( self, url ):
296*cdf0e10cSrcweir        items = self.mapPackageName2Path.items()
297*cdf0e10cSrcweir        for i in items:
298*cdf0e10cSrcweir            if url in i[1].pathes:
299*cdf0e10cSrcweir                self.mapPackageName2Path.pop(i[0])
300*cdf0e10cSrcweir                break
301*cdf0e10cSrcweir
302*cdf0e10cSrcweir    def addPackageByUrl( self, url ):
303*cdf0e10cSrcweir        packageName = self.getPackageNameFromUrl( url )
304*cdf0e10cSrcweir        transientPart = self.getTransientPartFromUrl( url )
305*cdf0e10cSrcweir        log.isDebugLevel() and log.debug( "addPackageByUrl : " + packageName + ", " + transientPart + "("+url+")" + ", rootUrl="+self.rootUrl )
306*cdf0e10cSrcweir        if self.mapPackageName2Path.has_key( packageName ):
307*cdf0e10cSrcweir            package = self.mapPackageName2Path[ packageName ]
308*cdf0e10cSrcweir            package.pathes = package.pathes + (url, )
309*cdf0e10cSrcweir        else:
310*cdf0e10cSrcweir            package = Package( (url,), transientPart)
311*cdf0e10cSrcweir            self.mapPackageName2Path[ packageName ] = package
312*cdf0e10cSrcweir
313*cdf0e10cSrcweir    def isUrlInPackage( self, url ):
314*cdf0e10cSrcweir        values = self.mapPackageName2Path.values()
315*cdf0e10cSrcweir        for i in values:
316*cdf0e10cSrcweir#	    print "checking " + url + " in " + str(i.pathes)
317*cdf0e10cSrcweir            if url in i.pathes:
318*cdf0e10cSrcweir               return True
319*cdf0e10cSrcweir#        print "false"
320*cdf0e10cSrcweir        return False
321*cdf0e10cSrcweir
322*cdf0e10cSrcweir    def setPackageAttributes( self, mapPackageName2Path, rootUrl ):
323*cdf0e10cSrcweir        self.mapPackageName2Path = mapPackageName2Path
324*cdf0e10cSrcweir        self.rootUrl = rootUrl
325*cdf0e10cSrcweir
326*cdf0e10cSrcweir    def getPersistentUrlFromStorageUrl( self, url ):
327*cdf0e10cSrcweir        # package name is the second directory
328*cdf0e10cSrcweir        ret = url
329*cdf0e10cSrcweir        if self.rootUrl:
330*cdf0e10cSrcweir            pos = len( self.rootUrl) +1
331*cdf0e10cSrcweir            ret = url[0:pos]+url[url.find("/",pos)+1:len(url)]
332*cdf0e10cSrcweir        log.isDebugLevel() and log.debug( "getPersistentUrlFromStorageUrl " + url +  " -> "+ ret)
333*cdf0e10cSrcweir        return ret
334*cdf0e10cSrcweir
335*cdf0e10cSrcweir    def getStorageUrlFromPersistentUrl( self, url):
336*cdf0e10cSrcweir        ret = url
337*cdf0e10cSrcweir        if self.rootUrl:
338*cdf0e10cSrcweir            pos = len(self.rootUrl)+1
339*cdf0e10cSrcweir            packageName = url[pos:url.find("/",pos+1)]
340*cdf0e10cSrcweir            package = self.mapPackageName2Path[ packageName ]
341*cdf0e10cSrcweir            ret = url[0:pos]+ package.transientPathElement + "/" + url[pos:len(url)]
342*cdf0e10cSrcweir        log.isDebugLevel() and log.debug( "getStorageUrlFromPersistentUrl " + url + " -> "+ ret)
343*cdf0e10cSrcweir        return ret
344*cdf0e10cSrcweir
345*cdf0e10cSrcweir    def getFuncsByUrl( self, url ):
346*cdf0e10cSrcweir        src = readTextFromStream( self.sfa.openFileRead( url ) )
347*cdf0e10cSrcweir        checkForPythonPathBesideScript( url[0:url.rfind('/')] )
348*cdf0e10cSrcweir        src = ensureSourceState( src )
349*cdf0e10cSrcweir
350*cdf0e10cSrcweir        code = compiler.parse( src )
351*cdf0e10cSrcweir
352*cdf0e10cSrcweir        allFuncs = []
353*cdf0e10cSrcweir
354*cdf0e10cSrcweir        if code == None:
355*cdf0e10cSrcweir            return allFuncs
356*cdf0e10cSrcweir
357*cdf0e10cSrcweir        g_exportedScripts = []
358*cdf0e10cSrcweir        for node in code.node.nodes:
359*cdf0e10cSrcweir            if node.__class__.__name__ == 'Function':
360*cdf0e10cSrcweir                allFuncs.append(node.name)
361*cdf0e10cSrcweir            elif node.__class__.__name__ == 'Assign':
362*cdf0e10cSrcweir                for assignee in node.nodes:
363*cdf0e10cSrcweir                    if assignee.name == 'g_exportedScripts':
364*cdf0e10cSrcweir                        for item in node.expr:
365*cdf0e10cSrcweir                            if item.__class__.__name__ == 'Name':
366*cdf0e10cSrcweir                                g_exportedScripts.append(item.name)
367*cdf0e10cSrcweir                        return g_exportedScripts
368*cdf0e10cSrcweir
369*cdf0e10cSrcweir        return allFuncs
370*cdf0e10cSrcweir
371*cdf0e10cSrcweir    def getModuleByUrl( self, url ):
372*cdf0e10cSrcweir        entry =  self.modules.get(url)
373*cdf0e10cSrcweir        load = True
374*cdf0e10cSrcweir        lastRead = self.sfa.getDateTimeModified( url )
375*cdf0e10cSrcweir        if entry:
376*cdf0e10cSrcweir            if hasChanged( entry.lastRead, lastRead ):
377*cdf0e10cSrcweir                log.isDebugLevel() and log.debug( "file " + url + " has changed, reloading" )
378*cdf0e10cSrcweir            else:
379*cdf0e10cSrcweir                load = False
380*cdf0e10cSrcweir
381*cdf0e10cSrcweir        if load:
382*cdf0e10cSrcweir            log.isDebugLevel() and log.debug( "opening >" + url + "<" )
383*cdf0e10cSrcweir
384*cdf0e10cSrcweir            src = readTextFromStream( self.sfa.openFileRead( url ) )
385*cdf0e10cSrcweir            checkForPythonPathBesideScript( url[0:url.rfind('/')] )
386*cdf0e10cSrcweir            src = ensureSourceState( src )
387*cdf0e10cSrcweir
388*cdf0e10cSrcweir            # execute the module
389*cdf0e10cSrcweir            entry = ModuleEntry( lastRead, imp.new_module("ooo_script_framework") )
390*cdf0e10cSrcweir            entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.scriptContext
391*cdf0e10cSrcweir
392*cdf0e10cSrcweir            code = None
393*cdf0e10cSrcweir            if url.startswith( "file:" ):
394*cdf0e10cSrcweir                code = compile( src, encfile(uno.fileUrlToSystemPath( url ) ), "exec" )
395*cdf0e10cSrcweir            else:
396*cdf0e10cSrcweir                code = compile( src, url, "exec" )
397*cdf0e10cSrcweir            exec code in entry.module.__dict__
398*cdf0e10cSrcweir            entry.module.__file__ = url
399*cdf0e10cSrcweir            self.modules[ url ] = entry
400*cdf0e10cSrcweir            log.isDebugLevel() and log.debug( "mapped " + url + " to " + str( entry.module ) )
401*cdf0e10cSrcweir        return  entry.module
402*cdf0e10cSrcweir
403*cdf0e10cSrcweir#--------------------------------------------------
404*cdf0e10cSrcweirdef isScript( candidate ):
405*cdf0e10cSrcweir    ret = False
406*cdf0e10cSrcweir    if isinstance( candidate, type(isScript) ):
407*cdf0e10cSrcweir        ret = True
408*cdf0e10cSrcweir    return ret
409*cdf0e10cSrcweir
410*cdf0e10cSrcweir#-------------------------------------------------------
411*cdf0e10cSrcweirclass ScriptBrowseNode( unohelper.Base, XBrowseNode , XPropertySet, XInvocation, XActionListener ):
412*cdf0e10cSrcweir    def __init__( self, provCtx, uri, fileName, funcName ):
413*cdf0e10cSrcweir        self.fileName = fileName
414*cdf0e10cSrcweir        self.funcName = funcName
415*cdf0e10cSrcweir        self.provCtx = provCtx
416*cdf0e10cSrcweir        self.uri = uri
417*cdf0e10cSrcweir
418*cdf0e10cSrcweir    def getName( self ):
419*cdf0e10cSrcweir        return self.funcName
420*cdf0e10cSrcweir
421*cdf0e10cSrcweir    def getChildNodes(self):
422*cdf0e10cSrcweir        return ()
423*cdf0e10cSrcweir
424*cdf0e10cSrcweir    def hasChildNodes(self):
425*cdf0e10cSrcweir        return False
426*cdf0e10cSrcweir
427*cdf0e10cSrcweir    def getType( self):
428*cdf0e10cSrcweir        return SCRIPT
429*cdf0e10cSrcweir
430*cdf0e10cSrcweir    def getPropertyValue( self, name ):
431*cdf0e10cSrcweir        ret = None
432*cdf0e10cSrcweir        try:
433*cdf0e10cSrcweir            if name == "URI":
434*cdf0e10cSrcweir                ret = self.provCtx.uriHelper.getScriptURI(
435*cdf0e10cSrcweir                    self.provCtx.getPersistentUrlFromStorageUrl( self.uri + "$" + self.funcName ) )
436*cdf0e10cSrcweir            elif name == "Editable" and ENABLE_EDIT_DIALOG:
437*cdf0e10cSrcweir                ret = not self.provCtx.sfa.isReadOnly( self.uri )
438*cdf0e10cSrcweir
439*cdf0e10cSrcweir            log.isDebugLevel() and log.debug( "ScriptBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) )
440*cdf0e10cSrcweir        except Exception,e:
441*cdf0e10cSrcweir            log.error( "ScriptBrowseNode.getPropertyValue error " + lastException2String())
442*cdf0e10cSrcweir            raise
443*cdf0e10cSrcweir
444*cdf0e10cSrcweir        return ret
445*cdf0e10cSrcweir    def setPropertyValue( self, name, value ):
446*cdf0e10cSrcweir        log.isDebugLevel() and log.debug( "ScriptBrowseNode.setPropertyValue called " + name + "=" +str(value ) )
447*cdf0e10cSrcweir    def getPropertySetInfo( self ):
448*cdf0e10cSrcweir        log.isDebugLevel() and log.debug( "ScriptBrowseNode.getPropertySetInfo called "  )
449*cdf0e10cSrcweir        return None
450*cdf0e10cSrcweir
451*cdf0e10cSrcweir    def getIntrospection( self ):
452*cdf0e10cSrcweir        return None
453*cdf0e10cSrcweir
454*cdf0e10cSrcweir    def invoke( self, name, params, outparamindex, outparams ):
455*cdf0e10cSrcweir        if name == "Editable":
456*cdf0e10cSrcweir            servicename = "com.sun.star.awt.DialogProvider"
457*cdf0e10cSrcweir            ctx = self.provCtx.scriptContext.getComponentContext()
458*cdf0e10cSrcweir            dlgprov = ctx.ServiceManager.createInstanceWithContext(
459*cdf0e10cSrcweir                servicename, ctx )
460*cdf0e10cSrcweir
461*cdf0e10cSrcweir            self.editor = dlgprov.createDialog(
462*cdf0e10cSrcweir                "vnd.sun.star.script:" +
463*cdf0e10cSrcweir                "ScriptBindingLibrary.MacroEditor?location=application")
464*cdf0e10cSrcweir
465*cdf0e10cSrcweir            code = readTextFromStream(self.provCtx.sfa.openFileRead(self.uri))
466*cdf0e10cSrcweir            code = ensureSourceState( code )
467*cdf0e10cSrcweir            self.editor.getControl("EditorTextField").setText(code)
468*cdf0e10cSrcweir
469*cdf0e10cSrcweir            self.editor.getControl("RunButton").setActionCommand("Run")
470*cdf0e10cSrcweir            self.editor.getControl("RunButton").addActionListener(self)
471*cdf0e10cSrcweir            self.editor.getControl("SaveButton").setActionCommand("Save")
472*cdf0e10cSrcweir            self.editor.getControl("SaveButton").addActionListener(self)
473*cdf0e10cSrcweir
474*cdf0e10cSrcweir            self.editor.execute()
475*cdf0e10cSrcweir
476*cdf0e10cSrcweir        return None
477*cdf0e10cSrcweir
478*cdf0e10cSrcweir    def actionPerformed( self, event ):
479*cdf0e10cSrcweir        try:
480*cdf0e10cSrcweir            if event.ActionCommand == "Run":
481*cdf0e10cSrcweir                code = self.editor.getControl("EditorTextField").getText()
482*cdf0e10cSrcweir                code = ensureSourceState( code )
483*cdf0e10cSrcweir                mod = imp.new_module("ooo_script_framework")
484*cdf0e10cSrcweir                mod.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.provCtx.scriptContext
485*cdf0e10cSrcweir                exec code in mod.__dict__
486*cdf0e10cSrcweir                values = mod.__dict__.get( CALLABLE_CONTAINER_NAME , None )
487*cdf0e10cSrcweir                if not values:
488*cdf0e10cSrcweir                    values = mod.__dict__.values()
489*cdf0e10cSrcweir
490*cdf0e10cSrcweir                for i in values:
491*cdf0e10cSrcweir                    if isScript( i ):
492*cdf0e10cSrcweir                        i()
493*cdf0e10cSrcweir                        break
494*cdf0e10cSrcweir
495*cdf0e10cSrcweir            elif event.ActionCommand == "Save":
496*cdf0e10cSrcweir                toWrite = uno.ByteSequence(
497*cdf0e10cSrcweir                    str(
498*cdf0e10cSrcweir                    self.editor.getControl("EditorTextField").getText().encode(
499*cdf0e10cSrcweir                    sys.getdefaultencoding())) )
500*cdf0e10cSrcweir                copyUrl = self.uri + ".orig"
501*cdf0e10cSrcweir                self.provCtx.sfa.move( self.uri, copyUrl )
502*cdf0e10cSrcweir                out = self.provCtx.sfa.openFileWrite( self.uri )
503*cdf0e10cSrcweir                out.writeBytes( toWrite )
504*cdf0e10cSrcweir                out.close()
505*cdf0e10cSrcweir                self.provCtx.sfa.kill( copyUrl )
506*cdf0e10cSrcweir#                log.isDebugLevel() and log.debug("Save is not implemented yet")
507*cdf0e10cSrcweir#                text = self.editor.getControl("EditorTextField").getText()
508*cdf0e10cSrcweir#                log.isDebugLevel() and log.debug("Would save: " + text)
509*cdf0e10cSrcweir        except Exception,e:
510*cdf0e10cSrcweir            # TODO: add an error box here !
511*cdf0e10cSrcweir            log.error( lastException2String() )
512*cdf0e10cSrcweir
513*cdf0e10cSrcweir
514*cdf0e10cSrcweir    def setValue( self, name, value ):
515*cdf0e10cSrcweir        return None
516*cdf0e10cSrcweir
517*cdf0e10cSrcweir    def getValue( self, name ):
518*cdf0e10cSrcweir        return None
519*cdf0e10cSrcweir
520*cdf0e10cSrcweir    def hasMethod( self, name ):
521*cdf0e10cSrcweir        return False
522*cdf0e10cSrcweir
523*cdf0e10cSrcweir    def hasProperty( self, name ):
524*cdf0e10cSrcweir        return False
525*cdf0e10cSrcweir
526*cdf0e10cSrcweir
527*cdf0e10cSrcweir#-------------------------------------------------------
528*cdf0e10cSrcweirclass FileBrowseNode( unohelper.Base, XBrowseNode ):
529*cdf0e10cSrcweir    def __init__( self, provCtx, uri , name ):
530*cdf0e10cSrcweir        self.provCtx = provCtx
531*cdf0e10cSrcweir        self.uri = uri
532*cdf0e10cSrcweir        self.name = name
533*cdf0e10cSrcweir        self.funcnames = None
534*cdf0e10cSrcweir
535*cdf0e10cSrcweir    def getName( self ):
536*cdf0e10cSrcweir        return self.name
537*cdf0e10cSrcweir
538*cdf0e10cSrcweir    def getChildNodes(self):
539*cdf0e10cSrcweir        ret = ()
540*cdf0e10cSrcweir        try:
541*cdf0e10cSrcweir            self.funcnames = self.provCtx.getFuncsByUrl( self.uri )
542*cdf0e10cSrcweir
543*cdf0e10cSrcweir            scriptNodeList = []
544*cdf0e10cSrcweir            for i in self.funcnames:
545*cdf0e10cSrcweir                scriptNodeList.append(
546*cdf0e10cSrcweir                    ScriptBrowseNode(
547*cdf0e10cSrcweir                    self.provCtx, self.uri, self.name, i ))
548*cdf0e10cSrcweir            ret = tuple( scriptNodeList )
549*cdf0e10cSrcweir            log.isDebugLevel() and log.debug( "returning " +str(len(ret)) + " ScriptChildNodes on " + self.uri )
550*cdf0e10cSrcweir        except Exception, e:
551*cdf0e10cSrcweir            text = lastException2String()
552*cdf0e10cSrcweir            log.error( "Error while evaluating " + self.uri + ":" + text )
553*cdf0e10cSrcweir            raise
554*cdf0e10cSrcweir        return ret
555*cdf0e10cSrcweir
556*cdf0e10cSrcweir    def hasChildNodes(self):
557*cdf0e10cSrcweir        try:
558*cdf0e10cSrcweir            return len(self.getChildNodes()) > 0
559*cdf0e10cSrcweir        except Exception, e:
560*cdf0e10cSrcweir            return False
561*cdf0e10cSrcweir
562*cdf0e10cSrcweir    def getType( self):
563*cdf0e10cSrcweir        return CONTAINER
564*cdf0e10cSrcweir
565*cdf0e10cSrcweir
566*cdf0e10cSrcweir
567*cdf0e10cSrcweirclass DirBrowseNode( unohelper.Base, XBrowseNode ):
568*cdf0e10cSrcweir    def __init__( self, provCtx, name, rootUrl ):
569*cdf0e10cSrcweir        self.provCtx = provCtx
570*cdf0e10cSrcweir        self.name = name
571*cdf0e10cSrcweir        self.rootUrl = rootUrl
572*cdf0e10cSrcweir
573*cdf0e10cSrcweir    def getName( self ):
574*cdf0e10cSrcweir        return self.name
575*cdf0e10cSrcweir
576*cdf0e10cSrcweir    def getChildNodes( self ):
577*cdf0e10cSrcweir        try:
578*cdf0e10cSrcweir            log.isDebugLevel() and log.debug( "DirBrowseNode.getChildNodes called for " + self.rootUrl )
579*cdf0e10cSrcweir            contents = self.provCtx.sfa.getFolderContents( self.rootUrl, True )
580*cdf0e10cSrcweir            browseNodeList = []
581*cdf0e10cSrcweir            for i in contents:
582*cdf0e10cSrcweir                if i.endswith( ".py" ):
583*cdf0e10cSrcweir                    log.isDebugLevel() and log.debug( "adding filenode " + i )
584*cdf0e10cSrcweir                    browseNodeList.append(
585*cdf0e10cSrcweir                        FileBrowseNode( self.provCtx, i, i[i.rfind("/")+1:len(i)-3] ) )
586*cdf0e10cSrcweir                elif self.provCtx.sfa.isFolder( i ) and not i.endswith("/pythonpath"):
587*cdf0e10cSrcweir                    log.isDebugLevel() and log.debug( "adding DirBrowseNode " + i )
588*cdf0e10cSrcweir                    browseNodeList.append( DirBrowseNode( self.provCtx, i[i.rfind("/")+1:len(i)],i))
589*cdf0e10cSrcweir            return tuple( browseNodeList )
590*cdf0e10cSrcweir        except Exception, e:
591*cdf0e10cSrcweir            text = lastException2String()
592*cdf0e10cSrcweir            log.error( "DirBrowseNode error: " + str(e) + " while evaluating " + self.rootUrl)
593*cdf0e10cSrcweir            log.error( text)
594*cdf0e10cSrcweir            return ()
595*cdf0e10cSrcweir
596*cdf0e10cSrcweir    def hasChildNodes( self ):
597*cdf0e10cSrcweir        return True
598*cdf0e10cSrcweir
599*cdf0e10cSrcweir    def getType( self ):
600*cdf0e10cSrcweir        return CONTAINER
601*cdf0e10cSrcweir
602*cdf0e10cSrcweir    def getScript( self, uri ):
603*cdf0e10cSrcweir        log.debug( "DirBrowseNode getScript " + uri + " invoked" )
604*cdf0e10cSrcweir        raise IllegalArgumentException( "DirBrowseNode couldn't instantiate script " + uri , self , 0 )
605*cdf0e10cSrcweir
606*cdf0e10cSrcweir
607*cdf0e10cSrcweirclass ManifestHandler( XDocumentHandler, unohelper.Base ):
608*cdf0e10cSrcweir    def __init__( self, rootUrl ):
609*cdf0e10cSrcweir        self.rootUrl = rootUrl
610*cdf0e10cSrcweir
611*cdf0e10cSrcweir    def startDocument( self ):
612*cdf0e10cSrcweir        self.urlList = []
613*cdf0e10cSrcweir
614*cdf0e10cSrcweir    def endDocument( self ):
615*cdf0e10cSrcweir        pass
616*cdf0e10cSrcweir
617*cdf0e10cSrcweir    def startElement( self , name, attlist):
618*cdf0e10cSrcweir        if name == "manifest:file-entry":
619*cdf0e10cSrcweir            if attlist.getValueByName( "manifest:media-type" ) == "application/vnd.sun.star.framework-script":
620*cdf0e10cSrcweir                self.urlList.append(
621*cdf0e10cSrcweir                    self.rootUrl + "/" + attlist.getValueByName( "manifest:full-path" ) )
622*cdf0e10cSrcweir
623*cdf0e10cSrcweir    def endElement( self, name ):
624*cdf0e10cSrcweir        pass
625*cdf0e10cSrcweir
626*cdf0e10cSrcweir    def characters ( self, chars ):
627*cdf0e10cSrcweir        pass
628*cdf0e10cSrcweir
629*cdf0e10cSrcweir    def ignoreableWhitespace( self, chars ):
630*cdf0e10cSrcweir        pass
631*cdf0e10cSrcweir
632*cdf0e10cSrcweir    def setDocumentLocator( self, locator ):
633*cdf0e10cSrcweir        pass
634*cdf0e10cSrcweir
635*cdf0e10cSrcweirdef isPyFileInPath( sfa, path ):
636*cdf0e10cSrcweir    ret = False
637*cdf0e10cSrcweir    contents = sfa.getFolderContents( path, True )
638*cdf0e10cSrcweir    for i in contents:
639*cdf0e10cSrcweir        if sfa.isFolder(i):
640*cdf0e10cSrcweir            ret = isPyFileInPath(sfa,i)
641*cdf0e10cSrcweir        else:
642*cdf0e10cSrcweir            if i.endswith(".py"):
643*cdf0e10cSrcweir                ret = True
644*cdf0e10cSrcweir        if ret:
645*cdf0e10cSrcweir            break
646*cdf0e10cSrcweir    return ret
647*cdf0e10cSrcweir
648*cdf0e10cSrcweir# extracts META-INF directory from
649*cdf0e10cSrcweirdef getPathesFromPackage( rootUrl, sfa ):
650*cdf0e10cSrcweir    ret = ()
651*cdf0e10cSrcweir    try:
652*cdf0e10cSrcweir        fileUrl = rootUrl + "/META-INF/manifest.xml"
653*cdf0e10cSrcweir        inputStream = sfa.openFileRead( fileUrl )
654*cdf0e10cSrcweir        parser = uno.getComponentContext().ServiceManager.createInstance( "com.sun.star.xml.sax.Parser" )
655*cdf0e10cSrcweir        handler = ManifestHandler( rootUrl )
656*cdf0e10cSrcweir        parser.setDocumentHandler( handler )
657*cdf0e10cSrcweir        parser.parseStream( InputSource( inputStream , "", fileUrl, fileUrl ) )
658*cdf0e10cSrcweir        for i in tuple(handler.urlList):
659*cdf0e10cSrcweir            if not isPyFileInPath( sfa, i ):
660*cdf0e10cSrcweir                handler.urlList.remove(i)
661*cdf0e10cSrcweir        ret = tuple( handler.urlList )
662*cdf0e10cSrcweir    except UnoException, e:
663*cdf0e10cSrcweir        text = lastException2String()
664*cdf0e10cSrcweir        log.debug( "getPathesFromPackage " + fileUrl + " Exception: " +text )
665*cdf0e10cSrcweir        pass
666*cdf0e10cSrcweir    return ret
667*cdf0e10cSrcweir
668*cdf0e10cSrcweir
669*cdf0e10cSrcweirclass Package:
670*cdf0e10cSrcweir    def __init__( self, pathes, transientPathElement ):
671*cdf0e10cSrcweir        self.pathes = pathes
672*cdf0e10cSrcweir        self.transientPathElement = transientPathElement
673*cdf0e10cSrcweir
674*cdf0e10cSrcweirclass DummyInteractionHandler( unohelper.Base, XInteractionHandler ):
675*cdf0e10cSrcweir    def __init__( self ):
676*cdf0e10cSrcweir        pass
677*cdf0e10cSrcweir    def handle( self, event):
678*cdf0e10cSrcweir        log.isDebugLevel() and log.debug( "pythonscript: DummyInteractionHandler.handle " + str( event ) )
679*cdf0e10cSrcweir
680*cdf0e10cSrcweirclass DummyProgressHandler( unohelper.Base, XProgressHandler ):
681*cdf0e10cSrcweir    def __init__( self ):
682*cdf0e10cSrcweir        pass
683*cdf0e10cSrcweir
684*cdf0e10cSrcweir    def push( self,status ):
685*cdf0e10cSrcweir        log.isDebugLevel() and log.debug( "pythonscript: DummyProgressHandler.push " + str( status ) )
686*cdf0e10cSrcweir    def update( self,status ):
687*cdf0e10cSrcweir        log.isDebugLevel() and log.debug( "pythonscript: DummyProgressHandler.update " + str( status ) )
688*cdf0e10cSrcweir    def pop( self ):
689*cdf0e10cSrcweir        log.isDebugLevel() and log.debug( "pythonscript: DummyProgressHandler.push " + str( event ) )
690*cdf0e10cSrcweir
691*cdf0e10cSrcweirclass CommandEnvironment(unohelper.Base, XCommandEnvironment):
692*cdf0e10cSrcweir    def __init__( self ):
693*cdf0e10cSrcweir        self.progressHandler = DummyProgressHandler()
694*cdf0e10cSrcweir        self.interactionHandler = DummyInteractionHandler()
695*cdf0e10cSrcweir    def getInteractionHandler( self ):
696*cdf0e10cSrcweir        return self.interactionHandler
697*cdf0e10cSrcweir    def getProgressHandler( self ):
698*cdf0e10cSrcweir        return self.progressHandler
699*cdf0e10cSrcweir
700*cdf0e10cSrcweir#maybe useful for debugging purposes
701*cdf0e10cSrcweir#class ModifyListener( unohelper.Base, XModifyListener ):
702*cdf0e10cSrcweir#    def __init__( self ):
703*cdf0e10cSrcweir#        pass
704*cdf0e10cSrcweir#    def modified( self, event ):
705*cdf0e10cSrcweir#        log.isDebugLevel() and log.debug( "pythonscript: ModifyListener.modified " + str( event ) )
706*cdf0e10cSrcweir#    def disposing( self, event ):
707*cdf0e10cSrcweir#        log.isDebugLevel() and log.debug( "pythonscript: ModifyListener.disposing " + str( event ) )
708*cdf0e10cSrcweir
709*cdf0e10cSrcweirdef mapStorageType2PackageContext( storageType ):
710*cdf0e10cSrcweir    ret = storageType
711*cdf0e10cSrcweir    if( storageType == "share:uno_packages" ):
712*cdf0e10cSrcweir        ret = "shared"
713*cdf0e10cSrcweir    if( storageType == "user:uno_packages" ):
714*cdf0e10cSrcweir        ret = "user"
715*cdf0e10cSrcweir    return ret
716*cdf0e10cSrcweir
717*cdf0e10cSrcweirdef getPackageName2PathMap( sfa, storageType ):
718*cdf0e10cSrcweir    ret = {}
719*cdf0e10cSrcweir    packageManagerFactory = uno.getComponentContext().getValueByName(
720*cdf0e10cSrcweir        "/singletons/com.sun.star.deployment.thePackageManagerFactory" )
721*cdf0e10cSrcweir    packageManager = packageManagerFactory.getPackageManager(
722*cdf0e10cSrcweir        mapStorageType2PackageContext(storageType))
723*cdf0e10cSrcweir#    packageManager.addModifyListener( ModifyListener() )
724*cdf0e10cSrcweir    log.isDebugLevel() and log.debug( "pythonscript: getPackageName2PathMap start getDeployedPackages" )
725*cdf0e10cSrcweir    packages = packageManager.getDeployedPackages(
726*cdf0e10cSrcweir        packageManager.createAbortChannel(), CommandEnvironment( ) )
727*cdf0e10cSrcweir    log.isDebugLevel() and log.debug( "pythonscript: getPackageName2PathMap end getDeployedPackages (" + str(len(packages))+")" )
728*cdf0e10cSrcweir
729*cdf0e10cSrcweir    for i in packages:
730*cdf0e10cSrcweir        log.isDebugLevel() and log.debug( "inspecting package " + i.Name + "("+i.Identifier.Value+")" )
731*cdf0e10cSrcweir        transientPathElement = penultimateElement( i.URL )
732*cdf0e10cSrcweir        j = expandUri( i.URL )
733*cdf0e10cSrcweir        pathes = getPathesFromPackage( j, sfa )
734*cdf0e10cSrcweir        if len( pathes ) > 0:
735*cdf0e10cSrcweir            # map package name to url, we need this later
736*cdf0e10cSrcweir            log.isErrorLevel() and log.error( "adding Package " + transientPathElement + " " + str( pathes ) )
737*cdf0e10cSrcweir            ret[ lastElement( j ) ] = Package( pathes, transientPathElement )
738*cdf0e10cSrcweir    return ret
739*cdf0e10cSrcweir
740*cdf0e10cSrcweirdef penultimateElement( aStr ):
741*cdf0e10cSrcweir    lastSlash = aStr.rindex("/")
742*cdf0e10cSrcweir    penultimateSlash = aStr.rindex("/",0,lastSlash-1)
743*cdf0e10cSrcweir    return  aStr[ penultimateSlash+1:lastSlash ]
744*cdf0e10cSrcweir
745*cdf0e10cSrcweirdef lastElement( aStr):
746*cdf0e10cSrcweir    return aStr[ aStr.rfind( "/" )+1:len(aStr)]
747*cdf0e10cSrcweir
748*cdf0e10cSrcweirclass PackageBrowseNode( unohelper.Base, XBrowseNode ):
749*cdf0e10cSrcweir    def __init__( self, provCtx, name, rootUrl ):
750*cdf0e10cSrcweir        self.provCtx = provCtx
751*cdf0e10cSrcweir        self.name = name
752*cdf0e10cSrcweir        self.rootUrl = rootUrl
753*cdf0e10cSrcweir
754*cdf0e10cSrcweir    def getName( self ):
755*cdf0e10cSrcweir        return self.name
756*cdf0e10cSrcweir
757*cdf0e10cSrcweir    def getChildNodes( self ):
758*cdf0e10cSrcweir        items = self.provCtx.mapPackageName2Path.items()
759*cdf0e10cSrcweir        browseNodeList = []
760*cdf0e10cSrcweir        for i in items:
761*cdf0e10cSrcweir            if len( i[1].pathes ) == 1:
762*cdf0e10cSrcweir                browseNodeList.append(
763*cdf0e10cSrcweir                    DirBrowseNode( self.provCtx, i[0], i[1].pathes[0] ))
764*cdf0e10cSrcweir            else:
765*cdf0e10cSrcweir                for j in i[1].pathes:
766*cdf0e10cSrcweir                    browseNodeList.append(
767*cdf0e10cSrcweir                        DirBrowseNode( self.provCtx, i[0]+"."+lastElement(j), j ) )
768*cdf0e10cSrcweir        return tuple( browseNodeList )
769*cdf0e10cSrcweir
770*cdf0e10cSrcweir    def hasChildNodes( self ):
771*cdf0e10cSrcweir        return len( self.mapPackageName2Path ) > 0
772*cdf0e10cSrcweir
773*cdf0e10cSrcweir    def getType( self ):
774*cdf0e10cSrcweir        return CONTAINER
775*cdf0e10cSrcweir
776*cdf0e10cSrcweir    def getScript( self, uri ):
777*cdf0e10cSrcweir        log.debug( "DirBrowseNode getScript " + uri + " invoked" )
778*cdf0e10cSrcweir        raise IllegalArgumentException( "PackageBrowseNode couldn't instantiate script " + uri , self , 0 )
779*cdf0e10cSrcweir
780*cdf0e10cSrcweir
781*cdf0e10cSrcweir
782*cdf0e10cSrcweir
783*cdf0e10cSrcweirclass PythonScript( unohelper.Base, XScript ):
784*cdf0e10cSrcweir    def __init__( self, func, mod ):
785*cdf0e10cSrcweir        self.func = func
786*cdf0e10cSrcweir        self.mod = mod
787*cdf0e10cSrcweir    def invoke(self, args, out, outindex ):
788*cdf0e10cSrcweir        log.isDebugLevel() and log.debug( "PythonScript.invoke " + str( args ) )
789*cdf0e10cSrcweir        try:
790*cdf0e10cSrcweir            ret = self.func( *args )
791*cdf0e10cSrcweir        except UnoException,e:
792*cdf0e10cSrcweir            # UNO Exception continue to fly ...
793*cdf0e10cSrcweir            text = lastException2String()
794*cdf0e10cSrcweir            complete = "Error during invoking function " + \
795*cdf0e10cSrcweir                str(self.func.__name__) + " in module " + \
796*cdf0e10cSrcweir                self.mod.__file__ + " (" + text + ")"
797*cdf0e10cSrcweir            log.isDebugLevel() and log.debug( complete )
798*cdf0e10cSrcweir            # some people may beat me up for modifying the exception text,
799*cdf0e10cSrcweir            # but otherwise office just shows
800*cdf0e10cSrcweir            # the type name and message text with no more information,
801*cdf0e10cSrcweir            # this is really bad for most users.
802*cdf0e10cSrcweir            e.Message = e.Message + " (" + complete + ")"
803*cdf0e10cSrcweir            raise
804*cdf0e10cSrcweir        except Exception,e:
805*cdf0e10cSrcweir            # General python exception are converted to uno RuntimeException
806*cdf0e10cSrcweir            text = lastException2String()
807*cdf0e10cSrcweir            complete = "Error during invoking function " + \
808*cdf0e10cSrcweir                str(self.func.__name__) + " in module " + \
809*cdf0e10cSrcweir                self.mod.__file__ + " (" + text + ")"
810*cdf0e10cSrcweir            log.isDebugLevel() and log.debug( complete )
811*cdf0e10cSrcweir            raise RuntimeException( complete , self )
812*cdf0e10cSrcweir        log.isDebugLevel() and log.debug( "PythonScript.invoke ret = " + str( ret ) )
813*cdf0e10cSrcweir        return ret, (), ()
814*cdf0e10cSrcweir
815*cdf0e10cSrcweirdef expandUri(  uri ):
816*cdf0e10cSrcweir    if uri.startswith( "vnd.sun.star.expand:" ):
817*cdf0e10cSrcweir        uri = uri.replace( "vnd.sun.star.expand:", "",1)
818*cdf0e10cSrcweir        uri = uno.getComponentContext().getByName(
819*cdf0e10cSrcweir                    "/singletons/com.sun.star.util.theMacroExpander" ).expandMacros( uri )
820*cdf0e10cSrcweir    if uri.startswith( "file:" ):
821*cdf0e10cSrcweir        uri = uno.absolutize("",uri)   # necessary to get rid of .. in uri
822*cdf0e10cSrcweir    return uri
823*cdf0e10cSrcweir
824*cdf0e10cSrcweir#--------------------------------------------------------------
825*cdf0e10cSrcweirclass PythonScriptProvider( unohelper.Base, XBrowseNode, XScriptProvider, XNameContainer):
826*cdf0e10cSrcweir    def __init__( self, ctx, *args ):
827*cdf0e10cSrcweir        if log.isDebugLevel():
828*cdf0e10cSrcweir            mystr = ""
829*cdf0e10cSrcweir            for i in args:
830*cdf0e10cSrcweir                if len(mystr) > 0:
831*cdf0e10cSrcweir                    mystr = mystr +","
832*cdf0e10cSrcweir                mystr = mystr + str(i)
833*cdf0e10cSrcweir            log.debug( "Entering PythonScriptProvider.ctor" + mystr )
834*cdf0e10cSrcweir
835*cdf0e10cSrcweir        storageType = ""
836*cdf0e10cSrcweir        if isinstance(args[0],unicode ):
837*cdf0e10cSrcweir            storageType = args[0]
838*cdf0e10cSrcweir        else:
839*cdf0e10cSrcweir            storageType = args[0].SCRIPTING_DOC_URI
840*cdf0e10cSrcweir        isPackage = storageType.endswith( ":uno_packages" )
841*cdf0e10cSrcweir
842*cdf0e10cSrcweir        try:
843*cdf0e10cSrcweir#            urlHelper = ctx.ServiceManager.createInstanceWithArgumentsAndContext(
844*cdf0e10cSrcweir#                "com.sun.star.script.provider.ScriptURIHelper", (LANGUAGENAME, storageType), ctx)
845*cdf0e10cSrcweir            urlHelper = MyUriHelper( ctx, storageType )
846*cdf0e10cSrcweir            log.isDebugLevel() and log.debug( "got urlHelper " + str( urlHelper ) )
847*cdf0e10cSrcweir
848*cdf0e10cSrcweir            rootUrl = expandUri( urlHelper.getRootStorageURI() )
849*cdf0e10cSrcweir            log.isDebugLevel() and log.debug( storageType + " transformed to " + rootUrl )
850*cdf0e10cSrcweir
851*cdf0e10cSrcweir            ucbService = "com.sun.star.ucb.SimpleFileAccess"
852*cdf0e10cSrcweir            sfa = ctx.ServiceManager.createInstanceWithContext( ucbService, ctx )
853*cdf0e10cSrcweir            if not sfa:
854*cdf0e10cSrcweir                log.debug("PythonScriptProvider couldn't instantiate " +ucbService)
855*cdf0e10cSrcweir                raise RuntimeException(
856*cdf0e10cSrcweir                    "PythonScriptProvider couldn't instantiate " +ucbService, self)
857*cdf0e10cSrcweir            self.provCtx = ProviderContext(
858*cdf0e10cSrcweir                storageType, sfa, urlHelper, ScriptContext( uno.getComponentContext(), None ) )
859*cdf0e10cSrcweir            if isPackage:
860*cdf0e10cSrcweir                mapPackageName2Path = getPackageName2PathMap( sfa, storageType )
861*cdf0e10cSrcweir                self.provCtx.setPackageAttributes( mapPackageName2Path , rootUrl )
862*cdf0e10cSrcweir                self.dirBrowseNode = PackageBrowseNode( self.provCtx, LANGUAGENAME, rootUrl )
863*cdf0e10cSrcweir            else:
864*cdf0e10cSrcweir                self.dirBrowseNode = DirBrowseNode( self.provCtx, LANGUAGENAME, rootUrl )
865*cdf0e10cSrcweir
866*cdf0e10cSrcweir        except Exception, e:
867*cdf0e10cSrcweir            text = lastException2String()
868*cdf0e10cSrcweir            log.debug( "PythonScriptProvider could not be instantiated because of : " + text )
869*cdf0e10cSrcweir            raise e
870*cdf0e10cSrcweir
871*cdf0e10cSrcweir    def getName( self ):
872*cdf0e10cSrcweir        return self.dirBrowseNode.getName()
873*cdf0e10cSrcweir
874*cdf0e10cSrcweir    def getChildNodes( self ):
875*cdf0e10cSrcweir        return self.dirBrowseNode.getChildNodes()
876*cdf0e10cSrcweir
877*cdf0e10cSrcweir    def hasChildNodes( self ):
878*cdf0e10cSrcweir        return self.dirBrowseNode.hasChildNodes()
879*cdf0e10cSrcweir
880*cdf0e10cSrcweir    def getType( self ):
881*cdf0e10cSrcweir        return self.dirBrowseNode.getType()
882*cdf0e10cSrcweir
883*cdf0e10cSrcweir    def getScript( self, uri ):
884*cdf0e10cSrcweir        log.debug( "DirBrowseNode getScript " + uri + " invoked" )
885*cdf0e10cSrcweir
886*cdf0e10cSrcweir        raise IllegalArgumentException( "DirBrowseNode couldn't instantiate script " + uri , self , 0 )
887*cdf0e10cSrcweir
888*cdf0e10cSrcweir    def getScript( self, scriptUri ):
889*cdf0e10cSrcweir        try:
890*cdf0e10cSrcweir            log.isDebugLevel() and log.debug( "getScript " + scriptUri + " invoked")
891*cdf0e10cSrcweir
892*cdf0e10cSrcweir            storageUri = self.provCtx.getStorageUrlFromPersistentUrl(
893*cdf0e10cSrcweir                self.provCtx.uriHelper.getStorageURI(scriptUri) );
894*cdf0e10cSrcweir            log.isDebugLevel() and log.debug( "getScript: storageUri = " + storageUri)
895*cdf0e10cSrcweir            fileUri = storageUri[0:storageUri.find( "$" )]
896*cdf0e10cSrcweir            funcName = storageUri[storageUri.find( "$" )+1:len(storageUri)]
897*cdf0e10cSrcweir
898*cdf0e10cSrcweir            mod = self.provCtx.getModuleByUrl( fileUri )
899*cdf0e10cSrcweir            log.isDebugLevel() and log.debug( " got mod " + str(mod) )
900*cdf0e10cSrcweir
901*cdf0e10cSrcweir            func = mod.__dict__[ funcName ]
902*cdf0e10cSrcweir
903*cdf0e10cSrcweir            log.isDebugLevel() and log.debug( "got func " + str( func ) )
904*cdf0e10cSrcweir            return PythonScript( func, mod )
905*cdf0e10cSrcweir        except Exception, e:
906*cdf0e10cSrcweir            text = lastException2String()
907*cdf0e10cSrcweir            log.error( text )
908*cdf0e10cSrcweir            raise ScriptFrameworkErrorException( text, self, scriptUri, LANGUAGENAME, 0 )
909*cdf0e10cSrcweir
910*cdf0e10cSrcweir
911*cdf0e10cSrcweir    # XServiceInfo
912*cdf0e10cSrcweir    def getSupportedServices( self ):
913*cdf0e10cSrcweir        return g_ImplementationHelper.getSupportedServices(g_implName)
914*cdf0e10cSrcweir
915*cdf0e10cSrcweir    def supportsService( self, ServiceName ):
916*cdf0e10cSrcweir        return g_ImplementationHelper.supportsService( g_implName, ServiceName )
917*cdf0e10cSrcweir
918*cdf0e10cSrcweir    def getImplementationName(self):
919*cdf0e10cSrcweir        return g_implName
920*cdf0e10cSrcweir
921*cdf0e10cSrcweir    def getByName( self, name ):
922*cdf0e10cSrcweir        log.debug( "getByName called" + str( name ))
923*cdf0e10cSrcweir        return None
924*cdf0e10cSrcweir
925*cdf0e10cSrcweir
926*cdf0e10cSrcweir    def getElementNames( self ):
927*cdf0e10cSrcweir        log.debug( "getElementNames called")
928*cdf0e10cSrcweir        return ()
929*cdf0e10cSrcweir
930*cdf0e10cSrcweir    def hasByName( self, name ):
931*cdf0e10cSrcweir        try:
932*cdf0e10cSrcweir            log.debug( "hasByName called " + str( name ))
933*cdf0e10cSrcweir            uri = expandUri(name)
934*cdf0e10cSrcweir            ret = self.provCtx.isUrlInPackage( uri )
935*cdf0e10cSrcweir            log.debug( "hasByName " + uri + " " +str( ret ) )
936*cdf0e10cSrcweir            return ret
937*cdf0e10cSrcweir        except Exception, e:
938*cdf0e10cSrcweir            text = lastException2String()
939*cdf0e10cSrcweir            log.debug( "Error in hasByName:" +  text )
940*cdf0e10cSrcweir            return False
941*cdf0e10cSrcweir
942*cdf0e10cSrcweir    def removeByName( self, name ):
943*cdf0e10cSrcweir        log.debug( "removeByName called" + str( name ))
944*cdf0e10cSrcweir        uri = expandUri( name )
945*cdf0e10cSrcweir        if self.provCtx.isUrlInPackage( uri ):
946*cdf0e10cSrcweir            self.provCtx.removePackageByUrl( uri )
947*cdf0e10cSrcweir        else:
948*cdf0e10cSrcweir            log.debug( "removeByName unknown uri " + str( name ) + ", ignoring" )
949*cdf0e10cSrcweir            raise NoSuchElementException( uri + "is not in package" , self )
950*cdf0e10cSrcweir        log.debug( "removeByName called" + str( uri ) + " successful" )
951*cdf0e10cSrcweir
952*cdf0e10cSrcweir    def insertByName( self, name, value ):
953*cdf0e10cSrcweir        log.debug( "insertByName called " + str( name ) + " " + str( value ))
954*cdf0e10cSrcweir        uri = expandUri( name )
955*cdf0e10cSrcweir        if isPyFileInPath( self.provCtx.sfa, uri ):
956*cdf0e10cSrcweir            self.provCtx.addPackageByUrl( uri )
957*cdf0e10cSrcweir        else:
958*cdf0e10cSrcweir            # package is no python package ...
959*cdf0e10cSrcweir            log.debug( "insertByName: no python files in " + str( uri ) + ", ignoring" )
960*cdf0e10cSrcweir            raise IllegalArgumentException( uri + " does not contain .py files", self, 1 )
961*cdf0e10cSrcweir        log.debug( "insertByName called " + str( uri ) + " successful" )
962*cdf0e10cSrcweir
963*cdf0e10cSrcweir    def replaceByName( self, name, value ):
964*cdf0e10cSrcweir        log.debug( "replaceByName called " + str( name ) + " " + str( value ))
965*cdf0e10cSrcweir        removeByName( name )
966*cdf0e10cSrcweir        insertByName( name )
967*cdf0e10cSrcweir        log.debug( "replaceByName called" + str( uri ) + " successful" )
968*cdf0e10cSrcweir
969*cdf0e10cSrcweir    def getElementType( self ):
970*cdf0e10cSrcweir        log.debug( "getElementType called" )
971*cdf0e10cSrcweir        return uno.getTypeByName( "void" )
972*cdf0e10cSrcweir
973*cdf0e10cSrcweir    def hasElements( self ):
974*cdf0e10cSrcweir        log.debug( "hasElements got called")
975*cdf0e10cSrcweir        return False
976*cdf0e10cSrcweir
977*cdf0e10cSrcweirg_ImplementationHelper.addImplementation( \
978*cdf0e10cSrcweir	PythonScriptProvider,g_implName, \
979*cdf0e10cSrcweir    ("com.sun.star.script.provider.LanguageScriptProvider",
980*cdf0e10cSrcweir     "com.sun.star.script.provider.ScriptProviderFor"+ LANGUAGENAME,),)
981*cdf0e10cSrcweir
982*cdf0e10cSrcweir
983*cdf0e10cSrcweirlog.debug( "pythonscript finished intializing" )
984*cdf0e10cSrcweir
985