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