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 31*15745147SPedro Giffunitry: 32*15745147SPedro Giffuni unicode 33*15745147SPedro Giffuniexcept NameError: 34*15745147SPedro Giffuni unicode = str 35*15745147SPedro Giffuni 36cdf0e10cSrcweirclass LogLevel: 37cdf0e10cSrcweir NONE = 0 38cdf0e10cSrcweir ERROR = 1 39cdf0e10cSrcweir DEBUG = 2 40cdf0e10cSrcweir 41cdf0e10cSrcweir# Configuration ---------------------------------------------------- 42cdf0e10cSrcweirLogLevel.use = LogLevel.NONE # production level 43cdf0e10cSrcweir#LogLevel.use = LogLevel.ERROR # for script developers 44cdf0e10cSrcweir#LogLevel.use = LogLevel.DEBUG # for script framework developers 45cdf0e10cSrcweirLOG_STDOUT = True # True, writes to stdout (difficult on windows) 46cdf0e10cSrcweir # False, writes to user/Scripts/python/log.txt 47cdf0e10cSrcweirENABLE_EDIT_DIALOG=False # offers a minimal editor for editing. 48cdf0e10cSrcweir#------------------------------------------------------------------- 49cdf0e10cSrcweir 50cdf0e10cSrcweirdef encfile(uni): 51cdf0e10cSrcweir return uni.encode( sys.getfilesystemencoding()) 52cdf0e10cSrcweir 53cdf0e10cSrcweirdef lastException2String(): 54cdf0e10cSrcweir (excType,excInstance,excTraceback) = sys.exc_info() 55cdf0e10cSrcweir ret = str(excType) + ": "+str(excInstance) + "\n" + \ 56cdf0e10cSrcweir uno._uno_extract_printable_stacktrace( excTraceback ) 57cdf0e10cSrcweir return ret 58cdf0e10cSrcweir 59cdf0e10cSrcweirdef logLevel2String( level ): 60cdf0e10cSrcweir ret = " NONE" 61cdf0e10cSrcweir if level == LogLevel.ERROR: 62cdf0e10cSrcweir ret = "ERROR" 63cdf0e10cSrcweir elif level >= LogLevel.DEBUG: 64cdf0e10cSrcweir ret = "DEBUG" 65cdf0e10cSrcweir return ret 66cdf0e10cSrcweir 67cdf0e10cSrcweirdef getLogTarget(): 68cdf0e10cSrcweir ret = sys.stdout 69cdf0e10cSrcweir if not LOG_STDOUT: 70cdf0e10cSrcweir try: 71cdf0e10cSrcweir pathSubst = uno.getComponentContext().ServiceManager.createInstance( 72cdf0e10cSrcweir "com.sun.star.util.PathSubstitution" ) 73cdf0e10cSrcweir userInstallation = pathSubst.getSubstituteVariableValue( "user" ) 74cdf0e10cSrcweir if len( userInstallation ) > 0: 75cdf0e10cSrcweir systemPath = uno.fileUrlToSystemPath( userInstallation + "/Scripts/python/log.txt" ) 76cdf0e10cSrcweir ret = file( systemPath , "a" ) 77*15745147SPedro Giffuni except Exception as e: 78*15745147SPedro Giffuni print("Exception during creation of pythonscript logfile: "+ lastException2String() + "\n, delagating log to stdout\n") 79cdf0e10cSrcweir return ret 8013cfd8dfSPedro Giffuni 81cdf0e10cSrcweirclass Logger(LogLevel): 82cdf0e10cSrcweir def __init__(self , target ): 83cdf0e10cSrcweir self.target = target 84cdf0e10cSrcweir 85cdf0e10cSrcweir def isDebugLevel( self ): 86cdf0e10cSrcweir return self.use >= self.DEBUG 8713cfd8dfSPedro Giffuni 88cdf0e10cSrcweir def debug( self, msg ): 89cdf0e10cSrcweir if self.isDebugLevel(): 90cdf0e10cSrcweir self.log( self.DEBUG, msg ) 9113cfd8dfSPedro Giffuni 92cdf0e10cSrcweir def isErrorLevel( self ): 93cdf0e10cSrcweir return self.use >= self.ERROR 94cdf0e10cSrcweir 95cdf0e10cSrcweir def error( self, msg ): 96cdf0e10cSrcweir if self.isErrorLevel(): 97cdf0e10cSrcweir self.log( self.ERROR, msg ) 98cdf0e10cSrcweir 99cdf0e10cSrcweir def log( self, level, msg ): 100cdf0e10cSrcweir if self.use >= level: 101cdf0e10cSrcweir try: 102cdf0e10cSrcweir self.target.write( 103cdf0e10cSrcweir time.asctime() + 104cdf0e10cSrcweir " [" + 105cdf0e10cSrcweir logLevel2String( level ) + 106cdf0e10cSrcweir "] " + 107cdf0e10cSrcweir encfile(msg) + 108cdf0e10cSrcweir "\n" ) 109cdf0e10cSrcweir self.target.flush() 110*15745147SPedro Giffuni except Exception as e: 111*15745147SPedro Giffuni print("Error during writing to stdout: " +lastException2String() + "\n") 112cdf0e10cSrcweir 113cdf0e10cSrcweirlog = Logger( getLogTarget() ) 114cdf0e10cSrcweir 115cdf0e10cSrcweirlog.debug( "pythonscript loading" ) 116cdf0e10cSrcweir 117cdf0e10cSrcweir#from com.sun.star.lang import typeOfXServiceInfo, typeOfXTypeProvider 118cdf0e10cSrcweirfrom com.sun.star.uno import RuntimeException 119cdf0e10cSrcweirfrom com.sun.star.lang import XServiceInfo 120cdf0e10cSrcweirfrom com.sun.star.io import IOException 12161c9e2f8SAriel Constenla-Hailefrom com.sun.star.ucb import CommandAbortedException, XCommandEnvironment, XProgressHandler, Command 122cdf0e10cSrcweirfrom com.sun.star.task import XInteractionHandler 12361c9e2f8SAriel Constenla-Hailefrom com.sun.star.beans import XPropertySet, Property 124cdf0e10cSrcweirfrom com.sun.star.container import XNameContainer 125cdf0e10cSrcweirfrom com.sun.star.xml.sax import XDocumentHandler, InputSource 126cdf0e10cSrcweirfrom com.sun.star.uno import Exception as UnoException 127cdf0e10cSrcweirfrom com.sun.star.script import XInvocation 128cdf0e10cSrcweirfrom com.sun.star.awt import XActionListener 129cdf0e10cSrcweir 130cdf0e10cSrcweirfrom com.sun.star.script.provider import XScriptProvider, XScript, XScriptContext, ScriptFrameworkErrorException 131cdf0e10cSrcweirfrom com.sun.star.script.browse import XBrowseNode 132cdf0e10cSrcweirfrom com.sun.star.script.browse.BrowseNodeTypes import SCRIPT, CONTAINER, ROOT 133cdf0e10cSrcweirfrom com.sun.star.util import XModifyListener 134cdf0e10cSrcweir 135cdf0e10cSrcweirLANGUAGENAME = "Python" 136cdf0e10cSrcweirGLOBAL_SCRIPTCONTEXT_NAME = "XSCRIPTCONTEXT" 137cdf0e10cSrcweirCALLABLE_CONTAINER_NAME = "g_exportedScripts" 138cdf0e10cSrcweir 139cdf0e10cSrcweir# pythonloader looks for a static g_ImplementationHelper variable 140cdf0e10cSrcweirg_ImplementationHelper = unohelper.ImplementationHelper() 141cdf0e10cSrcweirg_implName = "org.openoffice.pyuno.LanguageScriptProviderFor"+LANGUAGENAME 142cdf0e10cSrcweir 143cdf0e10cSrcweir 144cdf0e10cSrcweir 145cdf0e10cSrcweirBLOCK_SIZE = 65536 146cdf0e10cSrcweirdef readTextFromStream( inputStream ): 147cdf0e10cSrcweir # read the file 148cdf0e10cSrcweir code = uno.ByteSequence( "" ) 149cdf0e10cSrcweir while True: 150cdf0e10cSrcweir read,out = inputStream.readBytes( None , BLOCK_SIZE ) 151cdf0e10cSrcweir code = code + out 152cdf0e10cSrcweir if read < BLOCK_SIZE: 15313cfd8dfSPedro Giffuni break 154cdf0e10cSrcweir return code.value 15513cfd8dfSPedro Giffuni 156cdf0e10cSrcweirdef toIniName( str ): 157cdf0e10cSrcweir # TODO: what is the official way to get to know whether i am on the windows platform ? 158cdf0e10cSrcweir if( hasattr(sys , "dllhandle") ): 159cdf0e10cSrcweir return str + ".ini" 160cdf0e10cSrcweir return str + "rc" 161cdf0e10cSrcweir 162cdf0e10cSrcweir 163cdf0e10cSrcweir""" definition: storageURI is the system dependent, absolute file url, where the script is stored on disk 164cdf0e10cSrcweir scriptURI is the system independent uri 165cdf0e10cSrcweir""" 166cdf0e10cSrcweirclass MyUriHelper: 167cdf0e10cSrcweir 168cdf0e10cSrcweir def __init__( self, ctx, location ): 169cdf0e10cSrcweir self.s_UriMap = \ 170cdf0e10cSrcweir { "share" : "vnd.sun.star.expand:${$BRAND_BASE_DIR/program/" + toIniName( "bootstrap") + "::BaseInstallation}/share/Scripts/python" , \ 171cdf0e10cSrcweir "share:uno_packages" : "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE/uno_packages", \ 172cdf0e10cSrcweir "user" : "vnd.sun.star.expand:${$BRAND_BASE_DIR/program/" + toIniName( "bootstrap") + "::UserInstallation}/user/Scripts/python" , \ 17313cfd8dfSPedro Giffuni "user:uno_packages" : "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/uno_packages" } 174cdf0e10cSrcweir self.m_uriRefFac = ctx.ServiceManager.createInstanceWithContext("com.sun.star.uri.UriReferenceFactory",ctx) 175cdf0e10cSrcweir if location.startswith( "vnd.sun.star.tdoc" ): 176cdf0e10cSrcweir self.m_baseUri = location + "/Scripts/python" 177cdf0e10cSrcweir self.m_scriptUriLocation = "document" 178cdf0e10cSrcweir else: 179cdf0e10cSrcweir self.m_baseUri = expandUri( self.s_UriMap[location] ) 180cdf0e10cSrcweir self.m_scriptUriLocation = location 181735dd73bSPedro Giffuni log.debug( "initialized urihelper with baseUri="+self.m_baseUri + ",m_scriptUriLocation="+self.m_scriptUriLocation ) 18213cfd8dfSPedro Giffuni 183cdf0e10cSrcweir def getRootStorageURI( self ): 184cdf0e10cSrcweir return self.m_baseUri 18513cfd8dfSPedro Giffuni 186cdf0e10cSrcweir def getStorageURI( self, scriptURI ): 187cdf0e10cSrcweir return self.scriptURI2StorageUri(scriptURI) 188cdf0e10cSrcweir 189cdf0e10cSrcweir def getScriptURI( self, storageURI ): 190cdf0e10cSrcweir return self.storageURI2ScriptUri(storageURI) 191cdf0e10cSrcweir 192cdf0e10cSrcweir def storageURI2ScriptUri( self, storageURI ): 193cdf0e10cSrcweir if not storageURI.startswith( self.m_baseUri ): 194cdf0e10cSrcweir message = "pythonscript: storage uri '" + storageURI + "' not in base uri '" + self.m_baseUri + "'" 195735dd73bSPedro Giffuni log.debug( message ) 196cdf0e10cSrcweir raise RuntimeException( message ) 197cdf0e10cSrcweir 198cdf0e10cSrcweir ret = "vnd.sun.star.script:" + \ 199cdf0e10cSrcweir storageURI[len(self.m_baseUri)+1:].replace("/","|") + \ 200cdf0e10cSrcweir "?language=" + LANGUAGENAME + "&location=" + self.m_scriptUriLocation 201735dd73bSPedro Giffuni log.debug( "converting storageURI="+storageURI + " to scriptURI=" + ret ) 202cdf0e10cSrcweir return ret 20313cfd8dfSPedro Giffuni 204cdf0e10cSrcweir def scriptURI2StorageUri( self, scriptURI ): 205cdf0e10cSrcweir try: 206cdf0e10cSrcweir myUri = self.m_uriRefFac.parse(scriptURI) 207cdf0e10cSrcweir ret = self.m_baseUri + "/" + myUri.getName().replace( "|", "/" ) 208735dd73bSPedro Giffuni log.debug( "converting scriptURI="+scriptURI + " to storageURI=" + ret ) 209cdf0e10cSrcweir return ret 210*15745147SPedro Giffuni except UnoException as e: 211cdf0e10cSrcweir log.error( "error during converting scriptURI="+scriptURI + ": " + e.Message) 212cdf0e10cSrcweir raise RuntimeException( "pythonscript:scriptURI2StorageUri: " +e.getMessage(), None ) 213*15745147SPedro Giffuni except Exception as e: 214cdf0e10cSrcweir log.error( "error during converting scriptURI="+scriptURI + ": " + str(e)) 215cdf0e10cSrcweir raise RuntimeException( "pythonscript:scriptURI2StorageUri: " + str(e), None ) 21613cfd8dfSPedro Giffuni 217cdf0e10cSrcweir 218cdf0e10cSrcweirclass ModuleEntry: 219cdf0e10cSrcweir def __init__( self, lastRead, module ): 220cdf0e10cSrcweir self.lastRead = lastRead 221cdf0e10cSrcweir self.module = module 222cdf0e10cSrcweir 223cdf0e10cSrcweirdef hasChanged( oldDate, newDate ): 224cdf0e10cSrcweir return newDate.Year > oldDate.Year or \ 225cdf0e10cSrcweir newDate.Month > oldDate.Month or \ 226cdf0e10cSrcweir newDate.Day > oldDate.Day or \ 227cdf0e10cSrcweir newDate.Hours > oldDate.Hours or \ 228cdf0e10cSrcweir newDate.Minutes > oldDate.Minutes or \ 229cdf0e10cSrcweir newDate.Seconds > oldDate.Seconds or \ 230cdf0e10cSrcweir newDate.HundredthSeconds > oldDate.HundredthSeconds 231cdf0e10cSrcweir 232cdf0e10cSrcweirdef ensureSourceState( code ): 233cdf0e10cSrcweir if not code.endswith( "\n" ): 234cdf0e10cSrcweir code = code + "\n" 235cdf0e10cSrcweir code = code.replace( "\r", "" ) 236cdf0e10cSrcweir return code 237cdf0e10cSrcweir 238cdf0e10cSrcweir 239cdf0e10cSrcweirdef checkForPythonPathBesideScript( url ): 240cdf0e10cSrcweir if url.startswith( "file:" ): 241cdf0e10cSrcweir path = unohelper.fileUrlToSystemPath( url+"/pythonpath.zip" ); 242cdf0e10cSrcweir log.log( LogLevel.DEBUG, "checking for existence of " + path ) 243cdf0e10cSrcweir if 1 == os.access( encfile(path), os.F_OK) and not path in sys.path: 244cdf0e10cSrcweir log.log( LogLevel.DEBUG, "adding " + path + " to sys.path" ) 245cdf0e10cSrcweir sys.path.append( path ) 246cdf0e10cSrcweir 247cdf0e10cSrcweir path = unohelper.fileUrlToSystemPath( url+"/pythonpath" ); 248cdf0e10cSrcweir log.log( LogLevel.DEBUG, "checking for existence of " + path ) 249cdf0e10cSrcweir if 1 == os.access( encfile(path), os.F_OK) and not path in sys.path: 250cdf0e10cSrcweir log.log( LogLevel.DEBUG, "adding " + path + " to sys.path" ) 251cdf0e10cSrcweir sys.path.append( path ) 25213cfd8dfSPedro Giffuni 25313cfd8dfSPedro Giffuni 254cdf0e10cSrcweirclass ScriptContext(unohelper.Base): 25561c9e2f8SAriel Constenla-Haile def __init__( self, ctx, doc, inv ): 256cdf0e10cSrcweir self.ctx = ctx 257cdf0e10cSrcweir self.doc = doc 25861c9e2f8SAriel Constenla-Haile self.inv = inv 25913cfd8dfSPedro Giffuni 260cdf0e10cSrcweir # XScriptContext 261cdf0e10cSrcweir def getDocument(self): 26261c9e2f8SAriel Constenla-Haile if self.doc: 26361c9e2f8SAriel Constenla-Haile return self.doc 264cdf0e10cSrcweir return self.getDesktop().getCurrentComponent() 265cdf0e10cSrcweir 266cdf0e10cSrcweir def getDesktop(self): 267cdf0e10cSrcweir return self.ctx.ServiceManager.createInstanceWithContext( 268cdf0e10cSrcweir "com.sun.star.frame.Desktop", self.ctx ) 269cdf0e10cSrcweir 270cdf0e10cSrcweir def getComponentContext(self): 271cdf0e10cSrcweir return self.ctx 272cdf0e10cSrcweir 27361c9e2f8SAriel Constenla-Haile def getInvocationContext(self): 27461c9e2f8SAriel Constenla-Haile return self.inv 27561c9e2f8SAriel Constenla-Haile 276cdf0e10cSrcweir#---------------------------------- 277cdf0e10cSrcweir# Global Module Administration 278cdf0e10cSrcweir# does not fit together with script 279cdf0e10cSrcweir# engine lifetime management 280cdf0e10cSrcweir#---------------------------------- 281cdf0e10cSrcweir#g_scriptContext = ScriptContext( uno.getComponentContext(), None ) 282cdf0e10cSrcweir#g_modules = {} 283cdf0e10cSrcweir#def getModuleByUrl( url, sfa ): 284cdf0e10cSrcweir# entry = g_modules.get(url) 285cdf0e10cSrcweir# load = True 286cdf0e10cSrcweir# lastRead = sfa.getDateTimeModified( url ) 287cdf0e10cSrcweir# if entry: 288cdf0e10cSrcweir# if hasChanged( entry.lastRead, lastRead ): 289735dd73bSPedro Giffuni# log.debug("file " + url + " has changed, reloading") 290cdf0e10cSrcweir# else: 291cdf0e10cSrcweir# load = False 29213cfd8dfSPedro Giffuni# 293cdf0e10cSrcweir# if load: 294735dd73bSPedro Giffuni# log.debug( "opening >" + url + "<" ) 295cdf0e10cSrcweir# 296cdf0e10cSrcweir# code = readTextFromStream( sfa.openFileRead( url ) ) 29713cfd8dfSPedro Giffuni 298cdf0e10cSrcweir # execute the module 299cdf0e10cSrcweir# entry = ModuleEntry( lastRead, imp.new_module("ooo_script_framework") ) 300cdf0e10cSrcweir# entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = g_scriptContext 301cdf0e10cSrcweir# entry.module.__file__ = url 302cdf0e10cSrcweir# exec code in entry.module.__dict__ 303cdf0e10cSrcweir# g_modules[ url ] = entry 304735dd73bSPedro Giffuni# log.debug( "mapped " + url + " to " + str( entry.module ) ) 305cdf0e10cSrcweir# return entry.module 306cdf0e10cSrcweir 307cdf0e10cSrcweirclass ProviderContext: 308cdf0e10cSrcweir def __init__( self, storageType, sfa, uriHelper, scriptContext ): 309cdf0e10cSrcweir self.storageType = storageType 310cdf0e10cSrcweir self.sfa = sfa 311cdf0e10cSrcweir self.uriHelper = uriHelper 312cdf0e10cSrcweir self.scriptContext = scriptContext 313cdf0e10cSrcweir self.modules = {} 314cdf0e10cSrcweir self.rootUrl = None 315cdf0e10cSrcweir self.mapPackageName2Path = None 316cdf0e10cSrcweir 317cdf0e10cSrcweir def getTransientPartFromUrl( self, url ): 318cdf0e10cSrcweir rest = url.replace( self.rootUrl , "",1 ).replace( "/","",1) 319cdf0e10cSrcweir return rest[0:rest.find("/")] 32013cfd8dfSPedro Giffuni 321cdf0e10cSrcweir def getPackageNameFromUrl( self, url ): 322cdf0e10cSrcweir rest = url.replace( self.rootUrl , "",1 ).replace( "/","",1) 323cdf0e10cSrcweir start = rest.find("/") +1 324cdf0e10cSrcweir return rest[start:rest.find("/",start)] 32513cfd8dfSPedro Giffuni 32613cfd8dfSPedro Giffuni 327cdf0e10cSrcweir def removePackageByUrl( self, url ): 328*15745147SPedro Giffuni items = list(self.mapPackageName2Path.items()) 329cdf0e10cSrcweir for i in items: 330cdf0e10cSrcweir if url in i[1].pathes: 331cdf0e10cSrcweir self.mapPackageName2Path.pop(i[0]) 332cdf0e10cSrcweir break 333cdf0e10cSrcweir 334cdf0e10cSrcweir def addPackageByUrl( self, url ): 335cdf0e10cSrcweir packageName = self.getPackageNameFromUrl( url ) 336cdf0e10cSrcweir transientPart = self.getTransientPartFromUrl( url ) 337735dd73bSPedro Giffuni log.debug( "addPackageByUrl : " + packageName + ", " + transientPart + "("+url+")" + ", rootUrl="+self.rootUrl ) 338*15745147SPedro Giffuni if packageName in self.mapPackageName2Path: 339cdf0e10cSrcweir package = self.mapPackageName2Path[ packageName ] 340cdf0e10cSrcweir package.pathes = package.pathes + (url, ) 341cdf0e10cSrcweir else: 342cdf0e10cSrcweir package = Package( (url,), transientPart) 343cdf0e10cSrcweir self.mapPackageName2Path[ packageName ] = package 34413cfd8dfSPedro Giffuni 345cdf0e10cSrcweir def isUrlInPackage( self, url ): 346*15745147SPedro Giffuni values = list(self.mapPackageName2Path.values()) 347cdf0e10cSrcweir for i in values: 34813cfd8dfSPedro Giffuni# print "checking " + url + " in " + str(i.pathes) 349cdf0e10cSrcweir if url in i.pathes: 35013cfd8dfSPedro Giffuni return True 351cdf0e10cSrcweir# print "false" 352cdf0e10cSrcweir return False 35313cfd8dfSPedro Giffuni 354cdf0e10cSrcweir def setPackageAttributes( self, mapPackageName2Path, rootUrl ): 355cdf0e10cSrcweir self.mapPackageName2Path = mapPackageName2Path 356cdf0e10cSrcweir self.rootUrl = rootUrl 35713cfd8dfSPedro Giffuni 358cdf0e10cSrcweir def getPersistentUrlFromStorageUrl( self, url ): 359cdf0e10cSrcweir # package name is the second directory 360cdf0e10cSrcweir ret = url 361cdf0e10cSrcweir if self.rootUrl: 362cdf0e10cSrcweir pos = len( self.rootUrl) +1 363cdf0e10cSrcweir ret = url[0:pos]+url[url.find("/",pos)+1:len(url)] 364735dd73bSPedro Giffuni log.debug( "getPersistentUrlFromStorageUrl " + url + " -> "+ ret) 365cdf0e10cSrcweir return ret 366cdf0e10cSrcweir 367cdf0e10cSrcweir def getStorageUrlFromPersistentUrl( self, url): 368cdf0e10cSrcweir ret = url 369cdf0e10cSrcweir if self.rootUrl: 370cdf0e10cSrcweir pos = len(self.rootUrl)+1 371cdf0e10cSrcweir packageName = url[pos:url.find("/",pos+1)] 372cdf0e10cSrcweir package = self.mapPackageName2Path[ packageName ] 373cdf0e10cSrcweir ret = url[0:pos]+ package.transientPathElement + "/" + url[pos:len(url)] 374735dd73bSPedro Giffuni log.debug( "getStorageUrlFromPersistentUrl " + url + " -> "+ ret) 375cdf0e10cSrcweir return ret 376cdf0e10cSrcweir 377cdf0e10cSrcweir def getFuncsByUrl( self, url ): 378cdf0e10cSrcweir src = readTextFromStream( self.sfa.openFileRead( url ) ) 379cdf0e10cSrcweir checkForPythonPathBesideScript( url[0:url.rfind('/')] ) 380cdf0e10cSrcweir src = ensureSourceState( src ) 381cdf0e10cSrcweir 382cdf0e10cSrcweir allFuncs = [] 383cdf0e10cSrcweir g_exportedScripts = [] 384cdf0e10cSrcweir 38513cfd8dfSPedro Giffuni a = ast.parse(src, url) 38613cfd8dfSPedro Giffuni 38713cfd8dfSPedro Giffuni if isinstance(a, ast.Module): 38813cfd8dfSPedro Giffuni for node in a.body: 38913cfd8dfSPedro Giffuni if isinstance(node, ast.FunctionDef): 39013cfd8dfSPedro Giffuni allFuncs.append(node.name) 39113cfd8dfSPedro Giffuni elif isinstance(node, ast.Assign): 39213cfd8dfSPedro Giffuni is_exported = False 39313cfd8dfSPedro Giffuni for subnode in node.targets: 39413cfd8dfSPedro Giffuni if isinstance(subnode, ast.Name) and \ 39513cfd8dfSPedro Giffuni subnode.id == "g_exportedScripts": 39613cfd8dfSPedro Giffuni is_exported = True 39713cfd8dfSPedro Giffuni break 39813cfd8dfSPedro Giffuni if is_exported: 39913cfd8dfSPedro Giffuni value_node = node.value 40013cfd8dfSPedro Giffuni if isinstance(value_node, ast.List) or \ 40113cfd8dfSPedro Giffuni isinstance(value_node, ast.Tuple): 40213cfd8dfSPedro Giffuni for elt in value_node.elts: 40313cfd8dfSPedro Giffuni if isinstance(elt, ast.Str): 40413cfd8dfSPedro Giffuni g_exportedScripts.append(elt.s) 40513cfd8dfSPedro Giffuni elif isinstance(elt, ast.Name): 40613cfd8dfSPedro Giffuni g_exportedScripts.append(elt.id) 40713cfd8dfSPedro Giffuni elif isinstance(value_node, ast.Str): 40813cfd8dfSPedro Giffuni g_exportedScripts.append(value_node.s) 40913cfd8dfSPedro Giffuni elif isinstance(value_node, ast.Name): 41013cfd8dfSPedro Giffuni g_exportedScripts.append(value_node.id) 41113cfd8dfSPedro Giffuni return g_exportedScripts 412cdf0e10cSrcweir return allFuncs 41313cfd8dfSPedro Giffuni 414cdf0e10cSrcweir def getModuleByUrl( self, url ): 415cdf0e10cSrcweir entry = self.modules.get(url) 416cdf0e10cSrcweir load = True 417cdf0e10cSrcweir lastRead = self.sfa.getDateTimeModified( url ) 418cdf0e10cSrcweir if entry: 419cdf0e10cSrcweir if hasChanged( entry.lastRead, lastRead ): 420735dd73bSPedro Giffuni log.debug( "file " + url + " has changed, reloading" ) 421cdf0e10cSrcweir else: 422cdf0e10cSrcweir load = False 42313cfd8dfSPedro Giffuni 424cdf0e10cSrcweir if load: 425735dd73bSPedro Giffuni log.debug( "opening >" + url + "<" ) 42613cfd8dfSPedro Giffuni 427cdf0e10cSrcweir src = readTextFromStream( self.sfa.openFileRead( url ) ) 428cdf0e10cSrcweir checkForPythonPathBesideScript( url[0:url.rfind('/')] ) 42913cfd8dfSPedro Giffuni src = ensureSourceState( src ) 43013cfd8dfSPedro Giffuni 431cdf0e10cSrcweir # execute the module 432cdf0e10cSrcweir entry = ModuleEntry( lastRead, imp.new_module("ooo_script_framework") ) 433cdf0e10cSrcweir entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.scriptContext 434cdf0e10cSrcweir 435cdf0e10cSrcweir code = None 436cdf0e10cSrcweir if url.startswith( "file:" ): 437cdf0e10cSrcweir code = compile( src, encfile(uno.fileUrlToSystemPath( url ) ), "exec" ) 438cdf0e10cSrcweir else: 439cdf0e10cSrcweir code = compile( src, url, "exec" ) 440*15745147SPedro Giffuni exec(code, entry.module.__dict__) 441cdf0e10cSrcweir entry.module.__file__ = url 442cdf0e10cSrcweir self.modules[ url ] = entry 443735dd73bSPedro Giffuni log.debug( "mapped " + url + " to " + str( entry.module ) ) 444cdf0e10cSrcweir return entry.module 44513cfd8dfSPedro Giffuni 446cdf0e10cSrcweir#-------------------------------------------------- 447cdf0e10cSrcweirdef isScript( candidate ): 448cdf0e10cSrcweir ret = False 449cdf0e10cSrcweir if isinstance( candidate, type(isScript) ): 450cdf0e10cSrcweir ret = True 451cdf0e10cSrcweir return ret 45213cfd8dfSPedro Giffuni 453cdf0e10cSrcweir#------------------------------------------------------- 454cdf0e10cSrcweirclass ScriptBrowseNode( unohelper.Base, XBrowseNode , XPropertySet, XInvocation, XActionListener ): 455cdf0e10cSrcweir def __init__( self, provCtx, uri, fileName, funcName ): 456cdf0e10cSrcweir self.fileName = fileName 457cdf0e10cSrcweir self.funcName = funcName 458cdf0e10cSrcweir self.provCtx = provCtx 459cdf0e10cSrcweir self.uri = uri 46013cfd8dfSPedro Giffuni 461cdf0e10cSrcweir def getName( self ): 462cdf0e10cSrcweir return self.funcName 463cdf0e10cSrcweir 464cdf0e10cSrcweir def getChildNodes(self): 465cdf0e10cSrcweir return () 466cdf0e10cSrcweir 467cdf0e10cSrcweir def hasChildNodes(self): 468cdf0e10cSrcweir return False 46913cfd8dfSPedro Giffuni 470cdf0e10cSrcweir def getType( self): 471cdf0e10cSrcweir return SCRIPT 472cdf0e10cSrcweir 473cdf0e10cSrcweir def getPropertyValue( self, name ): 474cdf0e10cSrcweir ret = None 475cdf0e10cSrcweir try: 476cdf0e10cSrcweir if name == "URI": 477cdf0e10cSrcweir ret = self.provCtx.uriHelper.getScriptURI( 478cdf0e10cSrcweir self.provCtx.getPersistentUrlFromStorageUrl( self.uri + "$" + self.funcName ) ) 479cdf0e10cSrcweir elif name == "Editable" and ENABLE_EDIT_DIALOG: 480cdf0e10cSrcweir ret = not self.provCtx.sfa.isReadOnly( self.uri ) 48113cfd8dfSPedro Giffuni 482735dd73bSPedro Giffuni log.debug( "ScriptBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) ) 483*15745147SPedro Giffuni except Exception as e: 484cdf0e10cSrcweir log.error( "ScriptBrowseNode.getPropertyValue error " + lastException2String()) 485cdf0e10cSrcweir raise 48613cfd8dfSPedro Giffuni 487cdf0e10cSrcweir return ret 488cdf0e10cSrcweir def setPropertyValue( self, name, value ): 489735dd73bSPedro Giffuni log.debug( "ScriptBrowseNode.setPropertyValue called " + name + "=" +str(value ) ) 490cdf0e10cSrcweir def getPropertySetInfo( self ): 491735dd73bSPedro Giffuni log.debug( "ScriptBrowseNode.getPropertySetInfo called " ) 492cdf0e10cSrcweir return None 49313cfd8dfSPedro Giffuni 494cdf0e10cSrcweir def getIntrospection( self ): 495cdf0e10cSrcweir return None 496cdf0e10cSrcweir 497cdf0e10cSrcweir def invoke( self, name, params, outparamindex, outparams ): 498cdf0e10cSrcweir if name == "Editable": 499cdf0e10cSrcweir servicename = "com.sun.star.awt.DialogProvider" 500cdf0e10cSrcweir ctx = self.provCtx.scriptContext.getComponentContext() 501cdf0e10cSrcweir dlgprov = ctx.ServiceManager.createInstanceWithContext( 502cdf0e10cSrcweir servicename, ctx ) 503cdf0e10cSrcweir 504cdf0e10cSrcweir self.editor = dlgprov.createDialog( 505cdf0e10cSrcweir "vnd.sun.star.script:" + 506cdf0e10cSrcweir "ScriptBindingLibrary.MacroEditor?location=application") 507cdf0e10cSrcweir 508cdf0e10cSrcweir code = readTextFromStream(self.provCtx.sfa.openFileRead(self.uri)) 509cdf0e10cSrcweir code = ensureSourceState( code ) 510cdf0e10cSrcweir self.editor.getControl("EditorTextField").setText(code) 511cdf0e10cSrcweir 512cdf0e10cSrcweir self.editor.getControl("RunButton").setActionCommand("Run") 513cdf0e10cSrcweir self.editor.getControl("RunButton").addActionListener(self) 514cdf0e10cSrcweir self.editor.getControl("SaveButton").setActionCommand("Save") 515cdf0e10cSrcweir self.editor.getControl("SaveButton").addActionListener(self) 516cdf0e10cSrcweir 517cdf0e10cSrcweir self.editor.execute() 518cdf0e10cSrcweir 519cdf0e10cSrcweir return None 520cdf0e10cSrcweir 521cdf0e10cSrcweir def actionPerformed( self, event ): 522cdf0e10cSrcweir try: 523cdf0e10cSrcweir if event.ActionCommand == "Run": 524cdf0e10cSrcweir code = self.editor.getControl("EditorTextField").getText() 525cdf0e10cSrcweir code = ensureSourceState( code ) 526cdf0e10cSrcweir mod = imp.new_module("ooo_script_framework") 527cdf0e10cSrcweir mod.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.provCtx.scriptContext 528*15745147SPedro Giffuni exec(code, mod.__dict__) 529cdf0e10cSrcweir values = mod.__dict__.get( CALLABLE_CONTAINER_NAME , None ) 530cdf0e10cSrcweir if not values: 531*15745147SPedro Giffuni values = list(mod.__dict__.values()) 53213cfd8dfSPedro Giffuni 533cdf0e10cSrcweir for i in values: 534cdf0e10cSrcweir if isScript( i ): 535cdf0e10cSrcweir i() 536cdf0e10cSrcweir break 53713cfd8dfSPedro Giffuni 538cdf0e10cSrcweir elif event.ActionCommand == "Save": 539cdf0e10cSrcweir toWrite = uno.ByteSequence( 540cdf0e10cSrcweir str( 541cdf0e10cSrcweir self.editor.getControl("EditorTextField").getText().encode( 542cdf0e10cSrcweir sys.getdefaultencoding())) ) 543cdf0e10cSrcweir copyUrl = self.uri + ".orig" 544cdf0e10cSrcweir self.provCtx.sfa.move( self.uri, copyUrl ) 545cdf0e10cSrcweir out = self.provCtx.sfa.openFileWrite( self.uri ) 546cdf0e10cSrcweir out.writeBytes( toWrite ) 547cdf0e10cSrcweir out.close() 548cdf0e10cSrcweir self.provCtx.sfa.kill( copyUrl ) 549735dd73bSPedro Giffuni# log.debug("Save is not implemented yet") 550cdf0e10cSrcweir# text = self.editor.getControl("EditorTextField").getText() 551735dd73bSPedro Giffuni# log.debug("Would save: " + text) 552*15745147SPedro Giffuni except Exception as e: 553cdf0e10cSrcweir # TODO: add an error box here ! 554cdf0e10cSrcweir log.error( lastException2String() ) 55513cfd8dfSPedro Giffuni 556cdf0e10cSrcweir 557cdf0e10cSrcweir def setValue( self, name, value ): 558cdf0e10cSrcweir return None 559cdf0e10cSrcweir 560cdf0e10cSrcweir def getValue( self, name ): 561cdf0e10cSrcweir return None 562cdf0e10cSrcweir 563cdf0e10cSrcweir def hasMethod( self, name ): 564cdf0e10cSrcweir return False 565cdf0e10cSrcweir 566cdf0e10cSrcweir def hasProperty( self, name ): 567cdf0e10cSrcweir return False 568cdf0e10cSrcweir 56913cfd8dfSPedro Giffuni 570cdf0e10cSrcweir#------------------------------------------------------- 571cdf0e10cSrcweirclass FileBrowseNode( unohelper.Base, XBrowseNode ): 572cdf0e10cSrcweir def __init__( self, provCtx, uri , name ): 573cdf0e10cSrcweir self.provCtx = provCtx 574cdf0e10cSrcweir self.uri = uri 575cdf0e10cSrcweir self.name = name 576cdf0e10cSrcweir self.funcnames = None 57713cfd8dfSPedro Giffuni 578cdf0e10cSrcweir def getName( self ): 579cdf0e10cSrcweir return self.name 58013cfd8dfSPedro Giffuni 581cdf0e10cSrcweir def getChildNodes(self): 582cdf0e10cSrcweir ret = () 583cdf0e10cSrcweir try: 584cdf0e10cSrcweir self.funcnames = self.provCtx.getFuncsByUrl( self.uri ) 58513cfd8dfSPedro Giffuni 586cdf0e10cSrcweir scriptNodeList = [] 587cdf0e10cSrcweir for i in self.funcnames: 588cdf0e10cSrcweir scriptNodeList.append( 589cdf0e10cSrcweir ScriptBrowseNode( 590cdf0e10cSrcweir self.provCtx, self.uri, self.name, i )) 591cdf0e10cSrcweir ret = tuple( scriptNodeList ) 592735dd73bSPedro Giffuni log.debug( "returning " +str(len(ret)) + " ScriptChildNodes on " + self.uri ) 593*15745147SPedro Giffuni except Exception as e: 594cdf0e10cSrcweir text = lastException2String() 595cdf0e10cSrcweir log.error( "Error while evaluating " + self.uri + ":" + text ) 596cdf0e10cSrcweir raise 597cdf0e10cSrcweir return ret 598cdf0e10cSrcweir 599cdf0e10cSrcweir def hasChildNodes(self): 600cdf0e10cSrcweir try: 601cdf0e10cSrcweir return len(self.getChildNodes()) > 0 602*15745147SPedro Giffuni except Exception as e: 603cdf0e10cSrcweir return False 60413cfd8dfSPedro Giffuni 605cdf0e10cSrcweir def getType( self): 606cdf0e10cSrcweir return CONTAINER 607cdf0e10cSrcweir 60813cfd8dfSPedro Giffuni 609cdf0e10cSrcweir 610cdf0e10cSrcweirclass DirBrowseNode( unohelper.Base, XBrowseNode ): 611cdf0e10cSrcweir def __init__( self, provCtx, name, rootUrl ): 612cdf0e10cSrcweir self.provCtx = provCtx 613cdf0e10cSrcweir self.name = name 614cdf0e10cSrcweir self.rootUrl = rootUrl 615cdf0e10cSrcweir 616cdf0e10cSrcweir def getName( self ): 617cdf0e10cSrcweir return self.name 618cdf0e10cSrcweir 619cdf0e10cSrcweir def getChildNodes( self ): 620cdf0e10cSrcweir try: 621735dd73bSPedro Giffuni log.debug( "DirBrowseNode.getChildNodes called for " + self.rootUrl ) 622cdf0e10cSrcweir contents = self.provCtx.sfa.getFolderContents( self.rootUrl, True ) 623cdf0e10cSrcweir browseNodeList = [] 624cdf0e10cSrcweir for i in contents: 625cdf0e10cSrcweir if i.endswith( ".py" ): 626735dd73bSPedro Giffuni log.debug( "adding filenode " + i ) 627cdf0e10cSrcweir browseNodeList.append( 628cdf0e10cSrcweir FileBrowseNode( self.provCtx, i, i[i.rfind("/")+1:len(i)-3] ) ) 629cdf0e10cSrcweir elif self.provCtx.sfa.isFolder( i ) and not i.endswith("/pythonpath"): 630735dd73bSPedro Giffuni log.debug( "adding DirBrowseNode " + i ) 631cdf0e10cSrcweir browseNodeList.append( DirBrowseNode( self.provCtx, i[i.rfind("/")+1:len(i)],i)) 632cdf0e10cSrcweir return tuple( browseNodeList ) 633*15745147SPedro Giffuni except Exception as e: 634cdf0e10cSrcweir text = lastException2String() 635cdf0e10cSrcweir log.error( "DirBrowseNode error: " + str(e) + " while evaluating " + self.rootUrl) 636cdf0e10cSrcweir log.error( text) 637cdf0e10cSrcweir return () 638cdf0e10cSrcweir 639cdf0e10cSrcweir def hasChildNodes( self ): 640cdf0e10cSrcweir return True 641cdf0e10cSrcweir 642cdf0e10cSrcweir def getType( self ): 643cdf0e10cSrcweir return CONTAINER 644cdf0e10cSrcweir 645cdf0e10cSrcweir def getScript( self, uri ): 646cdf0e10cSrcweir log.debug( "DirBrowseNode getScript " + uri + " invoked" ) 647cdf0e10cSrcweir raise IllegalArgumentException( "DirBrowseNode couldn't instantiate script " + uri , self , 0 ) 648cdf0e10cSrcweir 649cdf0e10cSrcweir 650cdf0e10cSrcweirclass ManifestHandler( XDocumentHandler, unohelper.Base ): 651cdf0e10cSrcweir def __init__( self, rootUrl ): 652cdf0e10cSrcweir self.rootUrl = rootUrl 65313cfd8dfSPedro Giffuni 654cdf0e10cSrcweir def startDocument( self ): 655cdf0e10cSrcweir self.urlList = [] 65613cfd8dfSPedro Giffuni 657cdf0e10cSrcweir def endDocument( self ): 658cdf0e10cSrcweir pass 65913cfd8dfSPedro Giffuni 660cdf0e10cSrcweir def startElement( self , name, attlist): 661cdf0e10cSrcweir if name == "manifest:file-entry": 662cdf0e10cSrcweir if attlist.getValueByName( "manifest:media-type" ) == "application/vnd.sun.star.framework-script": 663cdf0e10cSrcweir self.urlList.append( 664cdf0e10cSrcweir self.rootUrl + "/" + attlist.getValueByName( "manifest:full-path" ) ) 665cdf0e10cSrcweir 666cdf0e10cSrcweir def endElement( self, name ): 667cdf0e10cSrcweir pass 668cdf0e10cSrcweir 669cdf0e10cSrcweir def characters ( self, chars ): 670cdf0e10cSrcweir pass 671cdf0e10cSrcweir 672cdf0e10cSrcweir def ignoreableWhitespace( self, chars ): 673cdf0e10cSrcweir pass 674cdf0e10cSrcweir 675cdf0e10cSrcweir def setDocumentLocator( self, locator ): 676cdf0e10cSrcweir pass 677cdf0e10cSrcweir 678cdf0e10cSrcweirdef isPyFileInPath( sfa, path ): 679cdf0e10cSrcweir ret = False 680cdf0e10cSrcweir contents = sfa.getFolderContents( path, True ) 681cdf0e10cSrcweir for i in contents: 682cdf0e10cSrcweir if sfa.isFolder(i): 683cdf0e10cSrcweir ret = isPyFileInPath(sfa,i) 684cdf0e10cSrcweir else: 685cdf0e10cSrcweir if i.endswith(".py"): 686cdf0e10cSrcweir ret = True 687cdf0e10cSrcweir if ret: 688cdf0e10cSrcweir break 689cdf0e10cSrcweir return ret 690cdf0e10cSrcweir 69113cfd8dfSPedro Giffuni# extracts META-INF directory from 692cdf0e10cSrcweirdef getPathesFromPackage( rootUrl, sfa ): 693cdf0e10cSrcweir ret = () 694cdf0e10cSrcweir try: 69513cfd8dfSPedro Giffuni fileUrl = rootUrl + "/META-INF/manifest.xml" 696cdf0e10cSrcweir inputStream = sfa.openFileRead( fileUrl ) 697cdf0e10cSrcweir parser = uno.getComponentContext().ServiceManager.createInstance( "com.sun.star.xml.sax.Parser" ) 698cdf0e10cSrcweir handler = ManifestHandler( rootUrl ) 699cdf0e10cSrcweir parser.setDocumentHandler( handler ) 700cdf0e10cSrcweir parser.parseStream( InputSource( inputStream , "", fileUrl, fileUrl ) ) 701cdf0e10cSrcweir for i in tuple(handler.urlList): 702cdf0e10cSrcweir if not isPyFileInPath( sfa, i ): 703cdf0e10cSrcweir handler.urlList.remove(i) 704cdf0e10cSrcweir ret = tuple( handler.urlList ) 705*15745147SPedro Giffuni except UnoException as e: 706cdf0e10cSrcweir text = lastException2String() 707cdf0e10cSrcweir log.debug( "getPathesFromPackage " + fileUrl + " Exception: " +text ) 708cdf0e10cSrcweir pass 709cdf0e10cSrcweir return ret 71013cfd8dfSPedro Giffuni 711cdf0e10cSrcweir 712cdf0e10cSrcweirclass Package: 713cdf0e10cSrcweir def __init__( self, pathes, transientPathElement ): 714cdf0e10cSrcweir self.pathes = pathes 715cdf0e10cSrcweir self.transientPathElement = transientPathElement 716cdf0e10cSrcweir 717cdf0e10cSrcweirclass DummyInteractionHandler( unohelper.Base, XInteractionHandler ): 718cdf0e10cSrcweir def __init__( self ): 719cdf0e10cSrcweir pass 720cdf0e10cSrcweir def handle( self, event): 721735dd73bSPedro Giffuni log.debug( "pythonscript: DummyInteractionHandler.handle " + str( event ) ) 722cdf0e10cSrcweir 723cdf0e10cSrcweirclass DummyProgressHandler( unohelper.Base, XProgressHandler ): 724cdf0e10cSrcweir def __init__( self ): 725cdf0e10cSrcweir pass 72613cfd8dfSPedro Giffuni 72713cfd8dfSPedro Giffuni def push( self,status ): 728735dd73bSPedro Giffuni log.debug( "pythonscript: DummyProgressHandler.push " + str( status ) ) 72913cfd8dfSPedro Giffuni def update( self,status ): 730735dd73bSPedro Giffuni log.debug( "pythonscript: DummyProgressHandler.update " + str( status ) ) 73113cfd8dfSPedro Giffuni def pop( self ): 732735dd73bSPedro Giffuni log.debug( "pythonscript: DummyProgressHandler.push " + str( event ) ) 733cdf0e10cSrcweir 734cdf0e10cSrcweirclass CommandEnvironment(unohelper.Base, XCommandEnvironment): 735cdf0e10cSrcweir def __init__( self ): 736cdf0e10cSrcweir self.progressHandler = DummyProgressHandler() 737cdf0e10cSrcweir self.interactionHandler = DummyInteractionHandler() 738cdf0e10cSrcweir def getInteractionHandler( self ): 739cdf0e10cSrcweir return self.interactionHandler 740cdf0e10cSrcweir def getProgressHandler( self ): 741cdf0e10cSrcweir return self.progressHandler 742cdf0e10cSrcweir 743cdf0e10cSrcweir#maybe useful for debugging purposes 744cdf0e10cSrcweir#class ModifyListener( unohelper.Base, XModifyListener ): 745cdf0e10cSrcweir# def __init__( self ): 746cdf0e10cSrcweir# pass 747cdf0e10cSrcweir# def modified( self, event ): 748735dd73bSPedro Giffuni# log.debug( "pythonscript: ModifyListener.modified " + str( event ) ) 749cdf0e10cSrcweir# def disposing( self, event ): 750735dd73bSPedro Giffuni# log.debug( "pythonscript: ModifyListener.disposing " + str( event ) ) 75161c9e2f8SAriel Constenla-Haile 75261c9e2f8SAriel Constenla-Hailedef getModelFromDocUrl(ctx, url): 75361c9e2f8SAriel Constenla-Haile """Get document model from document url.""" 75461c9e2f8SAriel Constenla-Haile doc = None 75561c9e2f8SAriel Constenla-Haile args = ("Local", "Office") 75661c9e2f8SAriel Constenla-Haile ucb = ctx.getServiceManager().createInstanceWithArgumentsAndContext( 75761c9e2f8SAriel Constenla-Haile "com.sun.star.ucb.UniversalContentBroker", args, ctx) 75861c9e2f8SAriel Constenla-Haile identifier = ucb.createContentIdentifier(url) 75961c9e2f8SAriel Constenla-Haile content = ucb.queryContent(identifier) 76061c9e2f8SAriel Constenla-Haile p = Property() 76161c9e2f8SAriel Constenla-Haile p.Name = "DocumentModel" 76261c9e2f8SAriel Constenla-Haile p.Handle = -1 76313cfd8dfSPedro Giffuni 76461c9e2f8SAriel Constenla-Haile c = Command() 76561c9e2f8SAriel Constenla-Haile c.Handle = -1 76661c9e2f8SAriel Constenla-Haile c.Name = "getPropertyValues" 76761c9e2f8SAriel Constenla-Haile c.Argument = uno.Any("[]com.sun.star.beans.Property", (p,)) 76813cfd8dfSPedro Giffuni 76961c9e2f8SAriel Constenla-Haile env = CommandEnvironment() 77061c9e2f8SAriel Constenla-Haile try: 77161c9e2f8SAriel Constenla-Haile ret = content.execute(c, 0, env) 77261c9e2f8SAriel Constenla-Haile doc = ret.getObject(1, None) 773*15745147SPedro Giffuni except Exception as e: 77461c9e2f8SAriel Constenla-Haile log.isErrorLevel() and log.error("getModelFromDocUrl: %s" % url) 77561c9e2f8SAriel Constenla-Haile return doc 77661c9e2f8SAriel Constenla-Haile 777cdf0e10cSrcweirdef mapStorageType2PackageContext( storageType ): 778cdf0e10cSrcweir ret = storageType 779cdf0e10cSrcweir if( storageType == "share:uno_packages" ): 780cdf0e10cSrcweir ret = "shared" 781cdf0e10cSrcweir if( storageType == "user:uno_packages" ): 782cdf0e10cSrcweir ret = "user" 783cdf0e10cSrcweir return ret 784cdf0e10cSrcweir 785cdf0e10cSrcweirdef getPackageName2PathMap( sfa, storageType ): 786cdf0e10cSrcweir ret = {} 787cdf0e10cSrcweir packageManagerFactory = uno.getComponentContext().getValueByName( 788cdf0e10cSrcweir "/singletons/com.sun.star.deployment.thePackageManagerFactory" ) 789cdf0e10cSrcweir packageManager = packageManagerFactory.getPackageManager( 790cdf0e10cSrcweir mapStorageType2PackageContext(storageType)) 791cdf0e10cSrcweir# packageManager.addModifyListener( ModifyListener() ) 792735dd73bSPedro Giffuni log.debug( "pythonscript: getPackageName2PathMap start getDeployedPackages" ) 793cdf0e10cSrcweir packages = packageManager.getDeployedPackages( 794cdf0e10cSrcweir packageManager.createAbortChannel(), CommandEnvironment( ) ) 795735dd73bSPedro Giffuni log.debug( "pythonscript: getPackageName2PathMap end getDeployedPackages (" + str(len(packages))+")" ) 796cdf0e10cSrcweir 797cdf0e10cSrcweir for i in packages: 798735dd73bSPedro Giffuni log.debug( "inspecting package " + i.Name + "("+i.Identifier.Value+")" ) 799cdf0e10cSrcweir transientPathElement = penultimateElement( i.URL ) 800cdf0e10cSrcweir j = expandUri( i.URL ) 801cdf0e10cSrcweir pathes = getPathesFromPackage( j, sfa ) 802cdf0e10cSrcweir if len( pathes ) > 0: 803cdf0e10cSrcweir # map package name to url, we need this later 804cdf0e10cSrcweir log.isErrorLevel() and log.error( "adding Package " + transientPathElement + " " + str( pathes ) ) 805cdf0e10cSrcweir ret[ lastElement( j ) ] = Package( pathes, transientPathElement ) 806cdf0e10cSrcweir return ret 807cdf0e10cSrcweir 808cdf0e10cSrcweirdef penultimateElement( aStr ): 809cdf0e10cSrcweir lastSlash = aStr.rindex("/") 810cdf0e10cSrcweir penultimateSlash = aStr.rindex("/",0,lastSlash-1) 811cdf0e10cSrcweir return aStr[ penultimateSlash+1:lastSlash ] 812cdf0e10cSrcweir 813cdf0e10cSrcweirdef lastElement( aStr): 814cdf0e10cSrcweir return aStr[ aStr.rfind( "/" )+1:len(aStr)] 815cdf0e10cSrcweir 816cdf0e10cSrcweirclass PackageBrowseNode( unohelper.Base, XBrowseNode ): 817cdf0e10cSrcweir def __init__( self, provCtx, name, rootUrl ): 818cdf0e10cSrcweir self.provCtx = provCtx 819cdf0e10cSrcweir self.name = name 820cdf0e10cSrcweir self.rootUrl = rootUrl 821cdf0e10cSrcweir 822cdf0e10cSrcweir def getName( self ): 823cdf0e10cSrcweir return self.name 824cdf0e10cSrcweir 825cdf0e10cSrcweir def getChildNodes( self ): 826*15745147SPedro Giffuni items = list(self.provCtx.mapPackageName2Path.items()) 827cdf0e10cSrcweir browseNodeList = [] 828cdf0e10cSrcweir for i in items: 829cdf0e10cSrcweir if len( i[1].pathes ) == 1: 830cdf0e10cSrcweir browseNodeList.append( 831cdf0e10cSrcweir DirBrowseNode( self.provCtx, i[0], i[1].pathes[0] )) 832cdf0e10cSrcweir else: 833cdf0e10cSrcweir for j in i[1].pathes: 834cdf0e10cSrcweir browseNodeList.append( 835cdf0e10cSrcweir DirBrowseNode( self.provCtx, i[0]+"."+lastElement(j), j ) ) 836cdf0e10cSrcweir return tuple( browseNodeList ) 837cdf0e10cSrcweir 838cdf0e10cSrcweir def hasChildNodes( self ): 839cdf0e10cSrcweir return len( self.mapPackageName2Path ) > 0 840cdf0e10cSrcweir 841cdf0e10cSrcweir def getType( self ): 842cdf0e10cSrcweir return CONTAINER 843cdf0e10cSrcweir 844cdf0e10cSrcweir def getScript( self, uri ): 845cdf0e10cSrcweir log.debug( "DirBrowseNode getScript " + uri + " invoked" ) 846cdf0e10cSrcweir raise IllegalArgumentException( "PackageBrowseNode couldn't instantiate script " + uri , self , 0 ) 847cdf0e10cSrcweir 848cdf0e10cSrcweir 849cdf0e10cSrcweir 850cdf0e10cSrcweir 851cdf0e10cSrcweirclass PythonScript( unohelper.Base, XScript ): 852cdf0e10cSrcweir def __init__( self, func, mod ): 853cdf0e10cSrcweir self.func = func 854cdf0e10cSrcweir self.mod = mod 855cdf0e10cSrcweir def invoke(self, args, out, outindex ): 856735dd73bSPedro Giffuni log.debug( "PythonScript.invoke " + str( args ) ) 857cdf0e10cSrcweir try: 858cdf0e10cSrcweir ret = self.func( *args ) 859*15745147SPedro Giffuni except UnoException as e: 860cdf0e10cSrcweir # UNO Exception continue to fly ... 861cdf0e10cSrcweir text = lastException2String() 862cdf0e10cSrcweir complete = "Error during invoking function " + \ 863cdf0e10cSrcweir str(self.func.__name__) + " in module " + \ 864cdf0e10cSrcweir self.mod.__file__ + " (" + text + ")" 865735dd73bSPedro Giffuni log.debug( complete ) 866cdf0e10cSrcweir # some people may beat me up for modifying the exception text, 867cdf0e10cSrcweir # but otherwise office just shows 868cdf0e10cSrcweir # the type name and message text with no more information, 86913cfd8dfSPedro Giffuni # this is really bad for most users. 870cdf0e10cSrcweir e.Message = e.Message + " (" + complete + ")" 871cdf0e10cSrcweir raise 872*15745147SPedro Giffuni except Exception as e: 873cdf0e10cSrcweir # General python exception are converted to uno RuntimeException 874cdf0e10cSrcweir text = lastException2String() 875cdf0e10cSrcweir complete = "Error during invoking function " + \ 876cdf0e10cSrcweir str(self.func.__name__) + " in module " + \ 877cdf0e10cSrcweir self.mod.__file__ + " (" + text + ")" 878735dd73bSPedro Giffuni log.debug( complete ) 879cdf0e10cSrcweir raise RuntimeException( complete , self ) 880735dd73bSPedro Giffuni log.debug( "PythonScript.invoke ret = " + str( ret ) ) 881cdf0e10cSrcweir return ret, (), () 882cdf0e10cSrcweir 883cdf0e10cSrcweirdef expandUri( uri ): 884cdf0e10cSrcweir if uri.startswith( "vnd.sun.star.expand:" ): 885cdf0e10cSrcweir uri = uri.replace( "vnd.sun.star.expand:", "",1) 886cdf0e10cSrcweir uri = uno.getComponentContext().getByName( 887cdf0e10cSrcweir "/singletons/com.sun.star.util.theMacroExpander" ).expandMacros( uri ) 888cdf0e10cSrcweir if uri.startswith( "file:" ): 889cdf0e10cSrcweir uri = uno.absolutize("",uri) # necessary to get rid of .. in uri 890cdf0e10cSrcweir return uri 89113cfd8dfSPedro Giffuni 892cdf0e10cSrcweir#-------------------------------------------------------------- 893cdf0e10cSrcweirclass PythonScriptProvider( unohelper.Base, XBrowseNode, XScriptProvider, XNameContainer): 894cdf0e10cSrcweir def __init__( self, ctx, *args ): 895cdf0e10cSrcweir if log.isDebugLevel(): 896cdf0e10cSrcweir mystr = "" 897cdf0e10cSrcweir for i in args: 898cdf0e10cSrcweir if len(mystr) > 0: 899cdf0e10cSrcweir mystr = mystr +"," 900cdf0e10cSrcweir mystr = mystr + str(i) 901cdf0e10cSrcweir log.debug( "Entering PythonScriptProvider.ctor" + mystr ) 902cdf0e10cSrcweir 90361c9e2f8SAriel Constenla-Haile doc = None 90461c9e2f8SAriel Constenla-Haile inv = None 905cdf0e10cSrcweir storageType = "" 90661c9e2f8SAriel Constenla-Haile 907cdf0e10cSrcweir if isinstance(args[0],unicode ): 908cdf0e10cSrcweir storageType = args[0] 90961c9e2f8SAriel Constenla-Haile if storageType.startswith( "vnd.sun.star.tdoc" ): 91061c9e2f8SAriel Constenla-Haile doc = getModelFromDocUrl(ctx, storageType) 911cdf0e10cSrcweir else: 91261c9e2f8SAriel Constenla-Haile inv = args[0] 91361c9e2f8SAriel Constenla-Haile try: 91461c9e2f8SAriel Constenla-Haile doc = inv.ScriptContainer 91561c9e2f8SAriel Constenla-Haile content = ctx.getServiceManager().createInstanceWithContext( 91613cfd8dfSPedro Giffuni "com.sun.star.frame.TransientDocumentsDocumentContentFactory", 91761c9e2f8SAriel Constenla-Haile ctx).createDocumentContent(doc) 91861c9e2f8SAriel Constenla-Haile storageType = content.getIdentifier().getContentIdentifier() 919*15745147SPedro Giffuni except Exception as e: 92061c9e2f8SAriel Constenla-Haile text = lastException2String() 92161c9e2f8SAriel Constenla-Haile log.error( text ) 92261c9e2f8SAriel Constenla-Haile 923cdf0e10cSrcweir isPackage = storageType.endswith( ":uno_packages" ) 924cdf0e10cSrcweir 925cdf0e10cSrcweir try: 926cdf0e10cSrcweir# urlHelper = ctx.ServiceManager.createInstanceWithArgumentsAndContext( 927cdf0e10cSrcweir# "com.sun.star.script.provider.ScriptURIHelper", (LANGUAGENAME, storageType), ctx) 928cdf0e10cSrcweir urlHelper = MyUriHelper( ctx, storageType ) 929735dd73bSPedro Giffuni log.debug( "got urlHelper " + str( urlHelper ) ) 93013cfd8dfSPedro Giffuni 931cdf0e10cSrcweir rootUrl = expandUri( urlHelper.getRootStorageURI() ) 932735dd73bSPedro Giffuni log.debug( storageType + " transformed to " + rootUrl ) 933cdf0e10cSrcweir 934cdf0e10cSrcweir ucbService = "com.sun.star.ucb.SimpleFileAccess" 935cdf0e10cSrcweir sfa = ctx.ServiceManager.createInstanceWithContext( ucbService, ctx ) 936cdf0e10cSrcweir if not sfa: 937cdf0e10cSrcweir log.debug("PythonScriptProvider couldn't instantiate " +ucbService) 938cdf0e10cSrcweir raise RuntimeException( 939cdf0e10cSrcweir "PythonScriptProvider couldn't instantiate " +ucbService, self) 940cdf0e10cSrcweir self.provCtx = ProviderContext( 94161c9e2f8SAriel Constenla-Haile storageType, sfa, urlHelper, ScriptContext( uno.getComponentContext(), doc, inv ) ) 942cdf0e10cSrcweir if isPackage: 943cdf0e10cSrcweir mapPackageName2Path = getPackageName2PathMap( sfa, storageType ) 944cdf0e10cSrcweir self.provCtx.setPackageAttributes( mapPackageName2Path , rootUrl ) 945cdf0e10cSrcweir self.dirBrowseNode = PackageBrowseNode( self.provCtx, LANGUAGENAME, rootUrl ) 946cdf0e10cSrcweir else: 947cdf0e10cSrcweir self.dirBrowseNode = DirBrowseNode( self.provCtx, LANGUAGENAME, rootUrl ) 94813cfd8dfSPedro Giffuni 949*15745147SPedro Giffuni except Exception as e: 950cdf0e10cSrcweir text = lastException2String() 951cdf0e10cSrcweir log.debug( "PythonScriptProvider could not be instantiated because of : " + text ) 952cdf0e10cSrcweir raise e 953cdf0e10cSrcweir 954cdf0e10cSrcweir def getName( self ): 955cdf0e10cSrcweir return self.dirBrowseNode.getName() 956cdf0e10cSrcweir 957cdf0e10cSrcweir def getChildNodes( self ): 95813cfd8dfSPedro Giffuni return self.dirBrowseNode.getChildNodes() 959cdf0e10cSrcweir 960cdf0e10cSrcweir def hasChildNodes( self ): 961cdf0e10cSrcweir return self.dirBrowseNode.hasChildNodes() 962cdf0e10cSrcweir 963cdf0e10cSrcweir def getType( self ): 964cdf0e10cSrcweir return self.dirBrowseNode.getType() 965cdf0e10cSrcweir 966cdf0e10cSrcweir def getScript( self, uri ): 967cdf0e10cSrcweir log.debug( "DirBrowseNode getScript " + uri + " invoked" ) 96813cfd8dfSPedro Giffuni 969cdf0e10cSrcweir raise IllegalArgumentException( "DirBrowseNode couldn't instantiate script " + uri , self , 0 ) 970cdf0e10cSrcweir 971cdf0e10cSrcweir def getScript( self, scriptUri ): 972cdf0e10cSrcweir try: 973735dd73bSPedro Giffuni log.debug( "getScript " + scriptUri + " invoked") 97413cfd8dfSPedro Giffuni 975cdf0e10cSrcweir storageUri = self.provCtx.getStorageUrlFromPersistentUrl( 976cdf0e10cSrcweir self.provCtx.uriHelper.getStorageURI(scriptUri) ); 977735dd73bSPedro Giffuni log.debug( "getScript: storageUri = " + storageUri) 978cdf0e10cSrcweir fileUri = storageUri[0:storageUri.find( "$" )] 97913cfd8dfSPedro Giffuni funcName = storageUri[storageUri.find( "$" )+1:len(storageUri)] 98013cfd8dfSPedro Giffuni 981cdf0e10cSrcweir mod = self.provCtx.getModuleByUrl( fileUri ) 982735dd73bSPedro Giffuni log.debug( " got mod " + str(mod) ) 98313cfd8dfSPedro Giffuni 984cdf0e10cSrcweir func = mod.__dict__[ funcName ] 985cdf0e10cSrcweir 986735dd73bSPedro Giffuni log.debug( "got func " + str( func ) ) 987cdf0e10cSrcweir return PythonScript( func, mod ) 988*15745147SPedro Giffuni except Exception as e: 989cdf0e10cSrcweir text = lastException2String() 990cdf0e10cSrcweir log.error( text ) 991cdf0e10cSrcweir raise ScriptFrameworkErrorException( text, self, scriptUri, LANGUAGENAME, 0 ) 99213cfd8dfSPedro Giffuni 993cdf0e10cSrcweir 994cdf0e10cSrcweir # XServiceInfo 995cdf0e10cSrcweir def getSupportedServices( self ): 996cdf0e10cSrcweir return g_ImplementationHelper.getSupportedServices(g_implName) 997cdf0e10cSrcweir 998cdf0e10cSrcweir def supportsService( self, ServiceName ): 999cdf0e10cSrcweir return g_ImplementationHelper.supportsService( g_implName, ServiceName ) 1000cdf0e10cSrcweir 1001cdf0e10cSrcweir def getImplementationName(self): 1002cdf0e10cSrcweir return g_implName 1003cdf0e10cSrcweir 1004cdf0e10cSrcweir def getByName( self, name ): 1005cdf0e10cSrcweir log.debug( "getByName called" + str( name )) 1006cdf0e10cSrcweir return None 1007cdf0e10cSrcweir 100813cfd8dfSPedro Giffuni 1009cdf0e10cSrcweir def getElementNames( self ): 1010cdf0e10cSrcweir log.debug( "getElementNames called") 1011cdf0e10cSrcweir return () 101213cfd8dfSPedro Giffuni 1013cdf0e10cSrcweir def hasByName( self, name ): 1014cdf0e10cSrcweir try: 1015cdf0e10cSrcweir log.debug( "hasByName called " + str( name )) 1016cdf0e10cSrcweir uri = expandUri(name) 1017cdf0e10cSrcweir ret = self.provCtx.isUrlInPackage( uri ) 1018cdf0e10cSrcweir log.debug( "hasByName " + uri + " " +str( ret ) ) 1019cdf0e10cSrcweir return ret 1020*15745147SPedro Giffuni except Exception as e: 1021cdf0e10cSrcweir text = lastException2String() 1022cdf0e10cSrcweir log.debug( "Error in hasByName:" + text ) 1023cdf0e10cSrcweir return False 1024cdf0e10cSrcweir 1025cdf0e10cSrcweir def removeByName( self, name ): 1026cdf0e10cSrcweir log.debug( "removeByName called" + str( name )) 1027cdf0e10cSrcweir uri = expandUri( name ) 1028cdf0e10cSrcweir if self.provCtx.isUrlInPackage( uri ): 1029cdf0e10cSrcweir self.provCtx.removePackageByUrl( uri ) 1030cdf0e10cSrcweir else: 1031cdf0e10cSrcweir log.debug( "removeByName unknown uri " + str( name ) + ", ignoring" ) 1032cdf0e10cSrcweir raise NoSuchElementException( uri + "is not in package" , self ) 1033cdf0e10cSrcweir log.debug( "removeByName called" + str( uri ) + " successful" ) 103413cfd8dfSPedro Giffuni 1035cdf0e10cSrcweir def insertByName( self, name, value ): 1036cdf0e10cSrcweir log.debug( "insertByName called " + str( name ) + " " + str( value )) 1037cdf0e10cSrcweir uri = expandUri( name ) 1038cdf0e10cSrcweir if isPyFileInPath( self.provCtx.sfa, uri ): 1039cdf0e10cSrcweir self.provCtx.addPackageByUrl( uri ) 1040cdf0e10cSrcweir else: 1041cdf0e10cSrcweir # package is no python package ... 1042cdf0e10cSrcweir log.debug( "insertByName: no python files in " + str( uri ) + ", ignoring" ) 1043cdf0e10cSrcweir raise IllegalArgumentException( uri + " does not contain .py files", self, 1 ) 1044cdf0e10cSrcweir log.debug( "insertByName called " + str( uri ) + " successful" ) 1045cdf0e10cSrcweir 1046cdf0e10cSrcweir def replaceByName( self, name, value ): 1047cdf0e10cSrcweir log.debug( "replaceByName called " + str( name ) + " " + str( value )) 1048cdf0e10cSrcweir removeByName( name ) 1049cdf0e10cSrcweir insertByName( name ) 1050cdf0e10cSrcweir log.debug( "replaceByName called" + str( uri ) + " successful" ) 1051cdf0e10cSrcweir 1052cdf0e10cSrcweir def getElementType( self ): 1053cdf0e10cSrcweir log.debug( "getElementType called" ) 1054cdf0e10cSrcweir return uno.getTypeByName( "void" ) 105513cfd8dfSPedro Giffuni 1056cdf0e10cSrcweir def hasElements( self ): 1057cdf0e10cSrcweir log.debug( "hasElements got called") 1058cdf0e10cSrcweir return False 105913cfd8dfSPedro Giffuni 1060cdf0e10cSrcweirg_ImplementationHelper.addImplementation( \ 106113cfd8dfSPedro Giffuni PythonScriptProvider,g_implName, \ 1062cdf0e10cSrcweir ("com.sun.star.script.provider.LanguageScriptProvider", 1063cdf0e10cSrcweir "com.sun.star.script.provider.ScriptProviderFor"+ LANGUAGENAME,),) 1064cdf0e10cSrcweir 1065cdf0e10cSrcweir 1066cdf0e10cSrcweirlog.debug( "pythonscript finished intializing" ) 1067