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