1# ************************************************************* 2# 3# Licensed to the Apache Software Foundation (ASF) under one 4# or more contributor license agreements. See the NOTICE file 5# distributed with this work for additional information 6# regarding copyright ownership. The ASF licenses this file 7# to you under the Apache License, Version 2.0 (the 8# "License"); you may not use this file except in compliance 9# with the License. You may obtain a copy of the License at 10# 11# http://www.apache.org/licenses/LICENSE-2.0 12# 13# Unless required by applicable law or agreed to in writing, 14# software distributed under the License is distributed on an 15# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16# KIND, either express or implied. See the License for the 17# specific language governing permissions and limitations 18# under the License. 19# 20# ************************************************************* 21 22# XScript implementation for python 23import uno 24import unohelper 25import sys 26import os 27import imp 28import time 29import ast 30 31try: 32 unicode 33except NameError: 34 unicode = str 35 36class LogLevel: 37 NONE = 0 # production level 38 ERROR = 1 # for script developers 39 DEBUG = 2 # for script framework developers 40 41PYSCRIPT_LOG_ENV = "PYSCRIPT_LOG_LEVEL" 42PYSCRIPT_LOG_STDOUT_ENV = "PYSCRIPT_LOG_STDOUT" 43 44# Configuration ---------------------------------------------------- 45LogLevel.use = LogLevel.NONE 46if os.environ.get(PYSCRIPT_LOG_ENV) == "ERROR": 47 LogLevel.use = LogLevel.ERROR 48elif os.environ.get(PYSCRIPT_LOG_ENV) == "DEBUG": 49 LogLevel.use = LogLevel.DEBUG 50 51# True, writes to stdout (difficult on windows) 52# False, writes to user/Scripts/python/log.txt 53LOG_STDOUT = os.environ.get(PYSCRIPT_LOG_STDOUT_ENV, "1") != "0" 54 55ENABLE_EDIT_DIALOG=True # offers a minimal editor for editing. 56#------------------------------------------------------------------- 57 58def encfile(uni): 59 if sys.version_info[0] > 2: 60 return uni 61 else: 62 return uni.encode( sys.getfilesystemencoding()) 63 64def lastException2String(): 65 (excType,excInstance,excTraceback) = sys.exc_info() 66 ret = str(excType) + ": "+str(excInstance) + "\n" + \ 67 uno._uno_extract_printable_stacktrace( excTraceback ) 68 return ret 69 70def logLevel2String( level ): 71 ret = " NONE" 72 if level == LogLevel.ERROR: 73 ret = "ERROR" 74 elif level >= LogLevel.DEBUG: 75 ret = "DEBUG" 76 return ret 77 78def getLogTarget(): 79 ret = sys.stdout 80 if not LOG_STDOUT: 81 try: 82 pathSubst = uno.getComponentContext().ServiceManager.createInstance( 83 "com.sun.star.util.PathSubstitution" ) 84 userInstallation = pathSubst.getSubstituteVariableValue( "user" ) 85 if len( userInstallation ) > 0: 86 systemPath = uno.fileUrlToSystemPath( userInstallation + "/Scripts/python/log.txt" ) 87 ret = open( systemPath , "a" ) 88 except Exception as e: 89 print("Exception during creation of pythonscript logfile: "+ lastException2String() + "\n, delagating log to stdout\n") 90 return ret 91 92class Logger(LogLevel): 93 def __init__(self , target ): 94 self.target = target 95 96 def isDebugLevel( self ): 97 return self.use >= self.DEBUG 98 99 def debug( self, msg ): 100 if self.isDebugLevel(): 101 self.log( self.DEBUG, msg ) 102 103 def isErrorLevel( self ): 104 return self.use >= self.ERROR 105 106 def error( self, msg ): 107 if self.isErrorLevel(): 108 self.log( self.ERROR, msg ) 109 110 def log( self, level, msg ): 111 if self.use >= level: 112 try: 113 self.target.write( 114 time.asctime() + 115 " [" + 116 logLevel2String( level ) + 117 "] " + 118 encfile(msg) + 119 "\n" ) 120 self.target.flush() 121 except Exception as e: 122 print("Error during writing to stdout: " +lastException2String() + "\n") 123 124log = Logger( getLogTarget() ) 125 126log.debug( "pythonscript loading" ) 127 128#from com.sun.star.lang import typeOfXServiceInfo, typeOfXTypeProvider 129from com.sun.star.uno import RuntimeException 130from com.sun.star.lang import XServiceInfo 131from com.sun.star.io import IOException, XInputStream 132from com.sun.star.ucb import CommandAbortedException, XCommandEnvironment, XProgressHandler, Command 133from com.sun.star.task import XInteractionHandler 134from com.sun.star.beans import XPropertySet, Property 135from com.sun.star.container import XNameContainer 136from com.sun.star.xml.sax import XDocumentHandler, InputSource 137from com.sun.star.uno import Exception as UnoException 138from com.sun.star.script import XInvocation 139from com.sun.star.awt import XActionListener 140 141from com.sun.star.script.provider import XScriptProvider, XScript, XScriptContext, ScriptFrameworkErrorException 142from com.sun.star.script.browse import XBrowseNode 143from com.sun.star.script.browse.BrowseNodeTypes import SCRIPT, CONTAINER, ROOT 144from com.sun.star.util import XModifyListener 145 146LANGUAGENAME = "Python" 147GLOBAL_SCRIPTCONTEXT_NAME = "XSCRIPTCONTEXT" 148CALLABLE_CONTAINER_NAME = "g_exportedScripts" 149 150# pythonloader looks for a static g_ImplementationHelper variable 151g_ImplementationHelper = unohelper.ImplementationHelper() 152g_implName = "org.openoffice.pyuno.LanguageScriptProviderFor"+LANGUAGENAME 153 154 155 156BLOCK_SIZE = 65536 157def readTextFromStream( inputStream ): 158 # read the file 159 code = uno.ByteSequence( b"" ) 160 while True: 161 read,out = inputStream.readBytes( None , BLOCK_SIZE ) 162 code = code + out 163 if read < BLOCK_SIZE: 164 break 165 if sys.version_info[0] > 2: 166 return str( code.value, 'utf-8' ) 167 else: 168 return code.value 169 170def toIniName( str ): 171 # TODO: what is the official way to get to know whether i am on the windows platform ? 172 if( hasattr(sys , "dllhandle") ): 173 return str + ".ini" 174 return str + "rc" 175 176class EmptyInputStream( unohelper.Base, XInputStream ): 177 def __init__( self ): 178 pass 179 180 def closeInput(self): 181 pass 182 183 def readBytes( self, seq, n ): 184 return 0, "" 185 186 def readSomeBytes( self, seq, n ): 187 return 0, "" 188 189 def skipBytes( self, n ): 190 pass 191 192 def available( self ): 193 return 0 194 195class BytesInputStream( unohelper.Base, XInputStream ): 196 def __init__( self, bytes ): 197 self.bytes = bytes 198 self.position = 0 199 200 def closeInput(self): 201 pass 202 203 def readBytes( self, seq, n ): 204 size = self.available() 205 if n < size: 206 size = n 207 curr = self.position 208 self.position += size 209 return size, uno.ByteSequence( self.bytes[curr:curr+size] ) 210 211 def readSomeBytes( self, seq, n ): 212 return self.readBytes( seq, n ) 213 214 def skipBytes( self, n ): 215 size = self.available() 216 if n < size: 217 size = n 218 self.position += size 219 220 def available( self ): 221 return len( self.bytes ) - self.position 222 223""" definition: storageURI is the system dependent, absolute file url, where the script is stored on disk 224 scriptURI is the system independent uri 225""" 226class MyUriHelper: 227 228 def __init__( self, ctx, location ): 229 self.s_UriMap = \ 230 { "share" : "vnd.sun.star.expand:${$OOO_BASE_DIR/program/" + toIniName( "bootstrap") + "::BaseInstallation}/share/Scripts/python" , \ 231 "share:uno_packages" : "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE/uno_packages", \ 232 "user" : "vnd.sun.star.expand:${$OOO_BASE_DIR/program/" + toIniName( "bootstrap") + "::UserInstallation}/user/Scripts/python" , \ 233 "user:uno_packages" : "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/uno_packages" } 234 self.m_uriRefFac = ctx.ServiceManager.createInstanceWithContext("com.sun.star.uri.UriReferenceFactory",ctx) 235 if location.startswith( "vnd.sun.star.tdoc" ): 236 self.m_baseUri = location + "/Scripts/python" 237 self.m_scriptUriLocation = "document" 238 else: 239 self.m_baseUri = expandUri( self.s_UriMap[location] ) 240 self.m_scriptUriLocation = location 241 log.debug( "initialized urihelper with baseUri="+self.m_baseUri + ",m_scriptUriLocation="+self.m_scriptUriLocation ) 242 243 def getRootStorageURI( self ): 244 return self.m_baseUri 245 246 def getStorageURI( self, scriptURI ): 247 return self.scriptURI2StorageUri(scriptURI) 248 249 def getScriptURI( self, storageURI ): 250 return self.storageURI2ScriptUri(storageURI) 251 252 def storageURI2ScriptUri( self, storageURI ): 253 if not storageURI.startswith( self.m_baseUri ): 254 message = "pythonscript: storage uri '" + storageURI + "' not in base uri '" + self.m_baseUri + "'" 255 log.debug( message ) 256 raise RuntimeException( message ) 257 258 ret = "vnd.sun.star.script:" + \ 259 storageURI[len(self.m_baseUri)+1:].replace("/","|") + \ 260 "?language=" + LANGUAGENAME + "&location=" + self.m_scriptUriLocation 261 log.debug( "converting storageURI="+storageURI + " to scriptURI=" + ret ) 262 return ret 263 264 def scriptURI2StorageUri( self, scriptURI ): 265 try: 266 myUri = self.m_uriRefFac.parse(scriptURI) 267 ret = self.m_baseUri + "/" + myUri.getName().replace( "|", "/" ) 268 log.debug( "converting scriptURI="+scriptURI + " to storageURI=" + ret ) 269 return ret 270 except UnoException as e: 271 log.error( "error during converting scriptURI="+scriptURI + ": " + e.Message) 272 raise RuntimeException( "pythonscript:scriptURI2StorageUri: " +e.getMessage(), None ) 273 except Exception as e: 274 log.error( "error during converting scriptURI="+scriptURI + ": " + str(e)) 275 raise RuntimeException( "pythonscript:scriptURI2StorageUri: " + str(e), None ) 276 277 278class ModuleEntry: 279 def __init__( self, lastRead, module ): 280 self.lastRead = lastRead 281 self.module = module 282 283def hasChanged( oldDate, newDate ): 284 return newDate.Year > oldDate.Year or \ 285 newDate.Month > oldDate.Month or \ 286 newDate.Day > oldDate.Day or \ 287 newDate.Hours > oldDate.Hours or \ 288 newDate.Minutes > oldDate.Minutes or \ 289 newDate.Seconds > oldDate.Seconds or \ 290 newDate.HundredthSeconds > oldDate.HundredthSeconds 291 292def ensureSourceState( code ): 293 if not code.endswith( "\n" ): 294 code = code + "\n" 295 code = code.replace( "\r", "" ) 296 return code 297 298 299def checkForPythonPathBesideScript( url ): 300 if url.startswith( "file:" ): 301 path = unohelper.fileUrlToSystemPath( url+"/pythonpath.zip" ); 302 log.log( LogLevel.DEBUG, "checking for existence of " + path ) 303 if 1 == os.access( encfile(path), os.F_OK) and not path in sys.path: 304 log.log( LogLevel.DEBUG, "adding " + path + " to sys.path" ) 305 sys.path.append( path ) 306 307 path = unohelper.fileUrlToSystemPath( url+"/pythonpath" ); 308 log.log( LogLevel.DEBUG, "checking for existence of " + path ) 309 if 1 == os.access( encfile(path), os.F_OK) and not path in sys.path: 310 log.log( LogLevel.DEBUG, "adding " + path + " to sys.path" ) 311 sys.path.append( path ) 312 313 314class ScriptContext(unohelper.Base): 315 def __init__( self, ctx, doc, inv ): 316 self.ctx = ctx 317 self.doc = doc 318 self.inv = inv 319 320 # XScriptContext 321 def getDocument(self): 322 if self.doc: 323 return self.doc 324 return self.getDesktop().getCurrentComponent() 325 326 def getDesktop(self): 327 return self.ctx.ServiceManager.createInstanceWithContext( 328 "com.sun.star.frame.Desktop", self.ctx ) 329 330 def getComponentContext(self): 331 return self.ctx 332 333 def getInvocationContext(self): 334 return self.inv 335 336#---------------------------------- 337# Global Module Administration 338# does not fit together with script 339# engine lifetime management 340#---------------------------------- 341#g_scriptContext = ScriptContext( uno.getComponentContext(), None ) 342#g_modules = {} 343#def getModuleByUrl( url, sfa ): 344# entry = g_modules.get(url) 345# load = True 346# lastRead = sfa.getDateTimeModified( url ) 347# if entry: 348# if hasChanged( entry.lastRead, lastRead ): 349# log.debug("file " + url + " has changed, reloading") 350# else: 351# load = False 352# 353# if load: 354# log.debug( "opening >" + url + "<" ) 355# 356# code = readTextFromStream( sfa.openFileRead( url ) ) 357 358 # execute the module 359# entry = ModuleEntry( lastRead, imp.new_module("ooo_script_framework") ) 360# entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = g_scriptContext 361# entry.module.__file__ = url 362# exec code in entry.module.__dict__ 363# g_modules[ url ] = entry 364# log.debug( "mapped " + url + " to " + str( entry.module ) ) 365# return entry.module 366 367class ProviderContext: 368 def __init__( self, storageType, sfa, uriHelper, scriptContext ): 369 self.storageType = storageType 370 self.sfa = sfa 371 self.uriHelper = uriHelper 372 self.scriptContext = scriptContext 373 self.modules = {} 374 self.rootUrl = None 375 self.mapPackageName2Path = None 376 377 def getTransientPartFromUrl( self, url ): 378 rest = url.replace( self.rootUrl , "",1 ).replace( "/","",1) 379 return rest[0:rest.find("/")] 380 381 def getPackageNameFromUrl( self, url ): 382 rest = url.replace( self.rootUrl , "",1 ).replace( "/","",1) 383 start = rest.find("/") +1 384 return rest[start:rest.find("/",start)] 385 386 387 def removePackageByUrl( self, url ): 388 items = list(self.mapPackageName2Path.items()) 389 for i in items: 390 if url in i[1].pathes: 391 self.mapPackageName2Path.pop(i[0]) 392 break 393 394 def addPackageByUrl( self, url ): 395 packageName = self.getPackageNameFromUrl( url ) 396 transientPart = self.getTransientPartFromUrl( url ) 397 log.debug( "addPackageByUrl : " + packageName + ", " + transientPart + "("+url+")" + ", rootUrl="+self.rootUrl ) 398 if packageName in self.mapPackageName2Path: 399 package = self.mapPackageName2Path[ packageName ] 400 package.pathes = package.pathes + (url, ) 401 else: 402 package = Package( (url,), transientPart) 403 self.mapPackageName2Path[ packageName ] = package 404 405 def isUrlInPackage( self, url ): 406 values = list(self.mapPackageName2Path.values()) 407 for i in values: 408# print "checking " + url + " in " + str(i.pathes) 409 if url in i.pathes: 410 return True 411# print "false" 412 return False 413 414 def setPackageAttributes( self, mapPackageName2Path, rootUrl ): 415 self.mapPackageName2Path = mapPackageName2Path 416 self.rootUrl = rootUrl 417 418 def getPersistentUrlFromStorageUrl( self, url ): 419 # package name is the second directory 420 ret = url 421 if self.rootUrl: 422 pos = len( self.rootUrl) +1 423 ret = url[0:pos]+url[url.find("/",pos)+1:len(url)] 424 log.debug( "getPersistentUrlFromStorageUrl " + url + " -> "+ ret) 425 return ret 426 427 def getStorageUrlFromPersistentUrl( self, url): 428 ret = url 429 if self.rootUrl: 430 pos = len(self.rootUrl)+1 431 packageName = url[pos:url.find("/",pos+1)] 432 package = self.mapPackageName2Path[ packageName ] 433 ret = url[0:pos]+ package.transientPathElement + "/" + url[pos:len(url)] 434 log.debug( "getStorageUrlFromPersistentUrl " + url + " -> "+ ret) 435 return ret 436 437 def getFuncsByUrl( self, url ): 438 src = readTextFromStream( self.sfa.openFileRead( url ) ) 439 checkForPythonPathBesideScript( url[0:url.rfind('/')] ) 440 src = ensureSourceState( src ) 441 442 allFuncs = [] 443 g_exportedScripts = [] 444 445 a = ast.parse(src, url) 446 447 if isinstance(a, ast.Module): 448 for node in a.body: 449 if isinstance(node, ast.FunctionDef): 450 allFuncs.append(node.name) 451 elif isinstance(node, ast.Assign): 452 is_exported = False 453 for subnode in node.targets: 454 if isinstance(subnode, ast.Name) and \ 455 subnode.id == "g_exportedScripts": 456 is_exported = True 457 break 458 if is_exported: 459 value_node = node.value 460 if isinstance(value_node, ast.List) or \ 461 isinstance(value_node, ast.Tuple): 462 for elt in value_node.elts: 463 if isinstance(elt, ast.Str): 464 g_exportedScripts.append(elt.s) 465 elif isinstance(elt, ast.Name): 466 g_exportedScripts.append(elt.id) 467 elif isinstance(value_node, ast.Str): 468 g_exportedScripts.append(value_node.s) 469 elif isinstance(value_node, ast.Name): 470 g_exportedScripts.append(value_node.id) 471 return g_exportedScripts 472 return allFuncs 473 474 def getModuleByUrl( self, url ): 475 entry = self.modules.get(url) 476 load = True 477 lastRead = self.sfa.getDateTimeModified( url ) 478 if entry: 479 if hasChanged( entry.lastRead, lastRead ): 480 log.debug( "file " + url + " has changed, reloading" ) 481 else: 482 load = False 483 484 if load: 485 log.debug( "opening >" + url + "<" ) 486 487 src = readTextFromStream( self.sfa.openFileRead( url ) ) 488 checkForPythonPathBesideScript( url[0:url.rfind('/')] ) 489 src = ensureSourceState( src ) 490 491 # execute the module 492 entry = ModuleEntry( lastRead, imp.new_module("ooo_script_framework") ) 493 entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.scriptContext 494 495 code = None 496 if url.startswith( "file:" ): 497 code = compile( src, encfile(uno.fileUrlToSystemPath( url ) ), "exec" ) 498 else: 499 code = compile( src, url, "exec" ) 500 exec(code, entry.module.__dict__) 501 entry.module.__file__ = url 502 self.modules[ url ] = entry 503 log.debug( "mapped " + url + " to " + str( entry.module ) ) 504 return entry.module 505 506def createEditorDialog( ctx ): 507 smgr = ctx.ServiceManager 508 509 dialogModel = smgr.createInstanceWithContext( 510 "com.sun.star.awt.UnoControlDialogModel", ctx) 511 dialogModel.PositionX = 105 512 dialogModel.PositionY = 117 513 dialogModel.Width = 240 514 dialogModel.Height = 320 515 dialogModel.Closeable = True 516 dialogModel.Moveable = True 517 dialogModel.Title = "Python Macro Editor" 518 519 runButtonModel = dialogModel.createInstance( 520 "com.sun.star.awt.UnoControlButtonModel" ) 521 runButtonModel.PositionX = 57 522 runButtonModel.PositionY = 300 523 runButtonModel.Width = 40 524 runButtonModel.Height = 14 525 runButtonModel.TabIndex = 0 526 runButtonModel.Label = "Run" 527 528 saveButtonModel = dialogModel.createInstance( 529 "com.sun.star.awt.UnoControlButtonModel" ) 530 saveButtonModel.PositionX = 100 531 saveButtonModel.PositionY = 300 532 saveButtonModel.Width = 40 533 saveButtonModel.Height = 14 534 saveButtonModel.TabIndex = 1 535 saveButtonModel.Label = "Save" 536 537 closeButtonModel = dialogModel.createInstance( 538 "com.sun.star.awt.UnoControlButtonModel" ) 539 closeButtonModel.PositionX = 143 540 closeButtonModel.PositionY = 300 541 closeButtonModel.Width = 40 542 closeButtonModel.Height = 14 543 closeButtonModel.TabIndex = 2 544 closeButtonModel.PushButtonType = 2 # CANCEL 545 closeButtonModel.Label = "Close" 546 547 textFieldModel = dialogModel.createInstance( 548 "com.sun.star.awt.UnoControlEditModel" ) 549 textFieldModel.PositionX = 6 550 textFieldModel.PositionY = 6 551 textFieldModel.Width = 228 552 textFieldModel.Height = 288 553 textFieldModel.TabIndex = 3 554 textFieldModel.HScroll = True 555 textFieldModel.VScroll = True 556 textFieldModel.MultiLine = True 557 558 dialogModel.insertByName( "RunButton", runButtonModel ) 559 dialogModel.insertByName( "SaveButton", saveButtonModel ) 560 dialogModel.insertByName( "CloseButton", closeButtonModel ) 561 dialogModel.insertByName( "EditorTextField", textFieldModel ) 562 563 # create the dialog control and set the model 564 controlContainer = smgr.createInstanceWithContext( 565 "com.sun.star.awt.UnoControlDialog", ctx); 566 controlContainer.setModel(dialogModel); 567 568 # create a peer 569 toolkit = smgr.createInstanceWithContext( 570 "com.sun.star.awt.ExtToolkit", ctx); 571 572 controlContainer.setVisible(False); 573 controlContainer.createPeer(toolkit, None); 574 575 return controlContainer 576 577 578#-------------------------------------------------- 579def isScript( candidate ): 580 ret = False 581 if isinstance( candidate, type(isScript) ): 582 ret = True 583 return ret 584 585#------------------------------------------------------- 586class ScriptBrowseNode( unohelper.Base, XBrowseNode , XPropertySet, XInvocation, XActionListener ): 587 def __init__( self, provCtx, parent, fileName, funcName ): 588 self.parent = parent 589 self.fileName = fileName 590 self.funcName = funcName 591 self.provCtx = provCtx 592 593 def uri( self ): 594 return self.parent.uri() 595 596 def getName( self ): 597 return self.funcName 598 599 def getChildNodes(self): 600 return () 601 602 def hasChildNodes(self): 603 return False 604 605 def getType( self): 606 return SCRIPT 607 608 def getPropertyValue( self, name ): 609 ret = None 610 try: 611 if name == "URI": 612 ret = self.provCtx.uriHelper.getScriptURI( 613 self.provCtx.getPersistentUrlFromStorageUrl( self.uri() + "$" + self.funcName ) ) 614 elif name == "Editable" and ENABLE_EDIT_DIALOG: 615 ret = not self.provCtx.sfa.isReadOnly( self.uri() ) 616 617 log.debug( "ScriptBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) ) 618 except Exception as e: 619 log.error( "ScriptBrowseNode.getPropertyValue error " + lastException2String()) 620 raise 621 622 return ret 623 def setPropertyValue( self, name, value ): 624 log.debug( "ScriptBrowseNode.setPropertyValue called " + name + "=" +str(value ) ) 625 def getPropertySetInfo( self ): 626 log.debug( "ScriptBrowseNode.getPropertySetInfo called " ) 627 return None 628 629 def getIntrospection( self ): 630 return None 631 632 def invoke( self, name, params, outparamindex, outparams ): 633 if name == "Editable": 634 ctx = self.provCtx.scriptContext.getComponentContext() 635 636 self.editor = createEditorDialog( ctx ) 637 638 code = readTextFromStream(self.provCtx.sfa.openFileRead(self.uri())) 639 code = ensureSourceState( code ) 640 self.editor.getControl("EditorTextField").setText(code) 641 642 self.editor.getControl("RunButton").setActionCommand("Run") 643 self.editor.getControl("RunButton").addActionListener(self) 644 self.editor.getControl("SaveButton").setActionCommand("Save") 645 self.editor.getControl("SaveButton").addActionListener(self) 646 647 self.editor.execute() 648 649 return None, (), () 650 651 def actionPerformed( self, event ): 652 try: 653 if event.ActionCommand == "Run": 654 code = self.editor.getControl("EditorTextField").getText() 655 code = ensureSourceState( code ) 656 mod = imp.new_module("ooo_script_framework") 657 mod.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.provCtx.scriptContext 658 exec(code, mod.__dict__) 659 values = mod.__dict__.get( CALLABLE_CONTAINER_NAME , None ) 660 if not values: 661 values = list(mod.__dict__.values()) 662 663 for i in values: 664 if isScript( i ): 665 i() 666 break 667 668 elif event.ActionCommand == "Save": 669 toWrite = uno.ByteSequence( 670 self.editor.getControl("EditorTextField").getText().encode( 671 sys.getdefaultencoding())) 672 copyUrl = self.uri() + ".orig" 673 self.provCtx.sfa.move( self.uri(), copyUrl ) 674 log.debug( "Saving Python macro to URI " + self.uri() ) 675 self.provCtx.sfa.writeFile( self.uri(), BytesInputStream( toWrite.value ) ) 676 self.provCtx.sfa.kill( copyUrl ) 677# log.debug("Save is not implemented yet") 678# text = self.editor.getControl("EditorTextField").getText() 679# log.debug("Would save: " + text) 680 except Exception as e: 681 # TODO: add an error box here ! 682 log.error( lastException2String() ) 683 684 685 def setValue( self, name, value ): 686 return None 687 688 def getValue( self, name ): 689 return None 690 691 def hasMethod( self, name ): 692 return False 693 694 def hasProperty( self, name ): 695 return False 696 697 698#------------------------------------------------------- 699class FileBrowseNode( unohelper.Base, XBrowseNode, XPropertySet, XInvocation, XActionListener ): 700 def __init__( self, provCtx, parent, name ): 701 self.provCtx = provCtx 702 self.parent = parent 703 self.name = name 704 self.funcnames = None 705 706 def uri( self ): 707 return self.parent.rootUrl + "/" + self.name + ".py" 708 709 def getName( self ): 710 return self.name 711 712 def getChildNodes(self): 713 ret = () 714 try: 715 self.funcnames = self.provCtx.getFuncsByUrl( self.uri() ) 716 717 scriptNodeList = [] 718 for i in self.funcnames: 719 scriptNodeList.append( 720 ScriptBrowseNode( 721 self.provCtx, self, self.name, i )) 722 ret = tuple( scriptNodeList ) 723 except Exception as e: 724 text = lastException2String() 725 log.error( "FileBrowseNode.getChildNodes error while evaluating " + self.uri() + ":" + text ) 726 raise 727 return ret 728 729 def hasChildNodes(self): 730 try: 731 return len(self.getChildNodes()) > 0 732 except Exception as e: 733 return False 734 735 def getType( self): 736 return CONTAINER 737 738 # XPropertySet 739 740 def getPropertyValue( self, name ): 741 ret = None 742 try: 743 if name == "Editable": 744 ret = not self.provCtx.sfa.isReadOnly( self.uri() ) 745 elif name == "Deletable": 746 ret = not self.provCtx.sfa.isReadOnly( self.uri() ) 747 elif name == "Renamable": 748 ret = not self.provCtx.sfa.isReadOnly( self.uri() ) 749 750 log.debug( "FileBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) ) 751 except Exception as e: 752 log.error( "FileBrowseNode.getPropertyValue error " + lastException2String()) 753 raise 754 755 return ret 756 757 def setPropertyValue( self, name, value ): 758 log.debug( "FileBrowseNode.setPropertyValue called " + name + "=" +str(value ) ) 759 760 def getPropertySetInfo( self ): 761 log.debug( "FileBrowseNode.getPropertySetInfo called " ) 762 return None 763 764 # XInvocation 765 766 def getIntrospection( self ): 767 log.debug( "FileBrowseNode.getIntrospection() called" ) 768 return None 769 770 def invoke( self, name, params, outparamindex, outparams ): 771 log.debug("FileBrowseNode.invoke called for " + name + "," + str(params) + "," + str(outparamindex) + "," + str(outparams)) 772 try: 773 if name == "Editable": 774 ctx = self.provCtx.scriptContext.getComponentContext() 775 776 self.editor = createEditorDialog( ctx ) 777 778 code = readTextFromStream(self.provCtx.sfa.openFileRead(self.uri())) 779 code = ensureSourceState( code ) 780 self.editor.getControl("EditorTextField").setText(code) 781 782 self.editor.getControl("RunButton").setActionCommand("Run") 783 self.editor.getControl("RunButton").addActionListener(self) 784 self.editor.getControl("SaveButton").setActionCommand("Save") 785 self.editor.getControl("SaveButton").addActionListener(self) 786 787 self.editor.execute() 788 elif name == "Deletable": 789 self.provCtx.sfa.kill( self.uri() ) 790 return True, (), () 791 elif name == "Renamable": 792 if params is None or not params: 793 raise IllegalArgumentException( "invoke with Creatable needs the name in params" ) 794 newUri = self.parent.rootUrl + "/" + params[0] + ".py" 795 self.provCtx.sfa.move( self.uri(), newUri ) 796 self.name = params[0] 797 return self, (), () 798 except Exception as e: 799 log.error( "FileBrowseNode.invoke error " + lastException2String() ) 800 raise 801 return None, (), () 802 803 def setValue( self, name, value ): 804 return None 805 806 def getValue( self, name ): 807 log.debug( "FileBrowseNode.getValue() called" ) 808 return None 809 810 def hasMethod( self, name ): 811 return False 812 813 def hasProperty( self, name ): 814 return False 815 816 # XActionListener 817 818 def actionPerformed( self, event ): 819 try: 820 if event.ActionCommand == "Run": 821 code = self.editor.getControl("EditorTextField").getText() 822 code = ensureSourceState( code ) 823 mod = imp.new_module("ooo_script_framework") 824 mod.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.provCtx.scriptContext 825 exec(code, mod.__dict__) 826 values = mod.__dict__.get( CALLABLE_CONTAINER_NAME , None ) 827 if not values: 828 values = list(mod.__dict__.values()) 829 830 for i in values: 831 if isScript( i ): 832 i() 833 break 834 835 elif event.ActionCommand == "Save": 836 toWrite = uno.ByteSequence( 837 self.editor.getControl("EditorTextField").getText().encode( 838 sys.getdefaultencoding())) 839 copyUrl = self.uri() + ".orig" 840 self.provCtx.sfa.move( self.uri(), copyUrl ) 841 log.debug( "Saving Python macro to URI " + self.uri() ) 842 self.provCtx.sfa.writeFile( self.uri(), BytesInputStream( toWrite.value ) ) 843 self.provCtx.sfa.kill( copyUrl ) 844# log.debug("Save is not implemented yet") 845# text = self.editor.getControl("EditorTextField").getText() 846# log.debug("Would save: " + text) 847 except Exception as e: 848 # TODO: add an error box here ! 849 log.error( lastException2String() ) 850 851 852class DirBrowseNode( unohelper.Base, XBrowseNode, XPropertySet, XInvocation ): 853 def __init__( self, provCtx, name, rootUrl, depth ): 854 self.provCtx = provCtx 855 self.name = name 856 self.rootUrl = rootUrl 857 self.depth = depth 858 log.debug( "DirBrowseNode constructor for " + name + "," + rootUrl ) 859 860 def getName( self ): 861 return self.name 862 863 def getChildNodes( self ): 864 try: 865 log.debug( "DirBrowseNode.getChildNodes called for " + self.rootUrl ) 866 contents = self.provCtx.sfa.getFolderContents( self.rootUrl, True ) 867 browseNodeList = [] 868 for i in contents: 869 if i.endswith( ".py" ): 870 log.debug( "adding filenode " + i ) 871 browseNodeList.append( 872 FileBrowseNode( self.provCtx, self, i[i.rfind("/")+1:len(i)-3] ) ) 873 elif self.provCtx.sfa.isFolder( i ) and not i.endswith("/pythonpath"): 874 log.debug( "adding DirBrowseNode " + i ) 875 browseNodeList.append( 876 DirBrowseNode( self.provCtx, i[i.rfind("/")+1:len(i)], i, self.depth + 1 ) ) 877 return tuple( browseNodeList ) 878 except Exception as e: 879 text = lastException2String() 880 log.error( "DirBrowseNode error: " + str(e) + " while evaluating " + self.rootUrl) 881 log.error( text) 882 return () 883 884 def hasChildNodes( self ): 885 return True 886 887 def getType( self ): 888 return CONTAINER 889 890 # XScriptProvider 891 892 def getScript( self, uri ): 893 log.debug( "DirBrowseNode getScript " + uri + " invoked" ) 894 raise IllegalArgumentException( "DirBrowseNode couldn't instantiate script " + uri , self , 0 ) 895 896 # XPropertySet 897 898 def getPropertyValue( self, name ): 899 ret = None 900 try: 901 if name == "Creatable": 902 ret = True 903 elif name == "Deletable": 904 ret = self.depth > 0 and not self.provCtx.sfa.isReadOnly( self.rootUrl ) 905 elif name == "Renamable": 906 ret = self.depth > 0 and not self.provCtx.sfa.isReadOnly( self.rootUrl ) 907 908 log.debug( "DirBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) ) 909 except Exception as e: 910 log.error( "DirBrowseNode.getPropertyValue error " + lastException2String()) 911 raise 912 913 return ret 914 915 def setPropertyValue( self, name, value ): 916 log.debug( "DirBrowseNode.setPropertyValue called " + name + "=" +str(value ) ) 917 918 def getPropertySetInfo( self ): 919 log.debug( "DirBrowseNode.getPropertySetInfo called " ) 920 return None 921 922 # XInvocation 923 924 def getIntrospection( self ): 925 log.debug( "DirBrowseNode.getIntrospection() called" ) 926 return None 927 928 def invoke( self, name, params, outparamindex, outparams ): 929 log.debug("DirBrowseNode.invoke called for " + name + "," + str(params) + "," + str(outparamindex) + "," + str(outparams)) 930 try: 931 if name == "Creatable": 932 if params is None or not params: 933 raise IllegalArgumentException( "invoke with Creatable needs the name in params" ) 934 if self.depth == 0: 935 subFolderUrl = self.rootUrl + "/" + params[0] 936 self.provCtx.sfa.createFolder( subFolderUrl ) 937 childNode = DirBrowseNode( self.provCtx, subFolderUrl[subFolderUrl.rfind("/")+1:len(subFolderUrl)], subFolderUrl, self.depth + 1 ) 938 return childNode, (), () 939 else: 940 scriptUrl = self.rootUrl + "/" + params[0] + ".py" 941 # Creates an empty file 942 self.provCtx.sfa.writeFile( scriptUrl, EmptyInputStream() ) 943 childNode = FileBrowseNode( self.provCtx, self, params[0] ) 944 return childNode, (), () 945 elif name == "Deletable": 946 self.provCtx.sfa.kill( self.rootUrl ) 947 return True, (), () 948 elif name == "Renamable": 949 if params is None or not params: 950 raise IllegalArgumentException( "invoke with Renamable needs the name in params" ) 951 newUrl = self.rootUrl[0:self.rootUrl.rfind("/")+1] + params[0] 952 self.provCtx.sfa.move( self.rootUrl, newUrl ) 953 self.rootUrl = newUrl 954 self.name = params[0] 955 return self, (), () 956 except Exception as e: 957 log.error( "DirBrowseNode.invoke error: " + lastException2String()) 958 raise 959 return None, (), () 960 961 def setValue( self, name, value ): 962 return None 963 964 def getValue( self, name ): 965 log.debug( "DirBrowseNode.getValue() called" ) 966 return None 967 968 def hasMethod( self, name ): 969 return False 970 971 def hasProperty( self, name ): 972 return False 973 974 975class ManifestHandler( XDocumentHandler, unohelper.Base ): 976 def __init__( self, rootUrl ): 977 self.rootUrl = rootUrl 978 979 def startDocument( self ): 980 self.urlList = [] 981 982 def endDocument( self ): 983 pass 984 985 def startElement( self , name, attlist): 986 if name == "manifest:file-entry": 987 if attlist.getValueByName( "manifest:media-type" ) == "application/vnd.sun.star.framework-script": 988 self.urlList.append( 989 self.rootUrl + "/" + attlist.getValueByName( "manifest:full-path" ) ) 990 991 def endElement( self, name ): 992 pass 993 994 def characters ( self, chars ): 995 pass 996 997 def ignoreableWhitespace( self, chars ): 998 pass 999 1000 def setDocumentLocator( self, locator ): 1001 pass 1002 1003def isPyFileInPath( sfa, path ): 1004 ret = False 1005 contents = sfa.getFolderContents( path, True ) 1006 for i in contents: 1007 if sfa.isFolder(i): 1008 ret = isPyFileInPath(sfa,i) 1009 else: 1010 if i.endswith(".py"): 1011 ret = True 1012 if ret: 1013 break 1014 return ret 1015 1016# extracts META-INF directory from 1017def getPathesFromPackage( rootUrl, sfa ): 1018 ret = () 1019 try: 1020 fileUrl = rootUrl + "/META-INF/manifest.xml" 1021 inputStream = sfa.openFileRead( fileUrl ) 1022 parser = uno.getComponentContext().ServiceManager.createInstance( "com.sun.star.xml.sax.Parser" ) 1023 handler = ManifestHandler( rootUrl ) 1024 parser.setDocumentHandler( handler ) 1025 parser.parseStream( InputSource( inputStream , "", fileUrl, fileUrl ) ) 1026 for i in tuple(handler.urlList): 1027 if not isPyFileInPath( sfa, i ): 1028 handler.urlList.remove(i) 1029 ret = tuple( handler.urlList ) 1030 except UnoException as e: 1031 text = lastException2String() 1032 log.debug( "getPathesFromPackage " + fileUrl + " Exception: " +text ) 1033 pass 1034 return ret 1035 1036 1037class Package: 1038 def __init__( self, pathes, transientPathElement ): 1039 self.pathes = pathes 1040 self.transientPathElement = transientPathElement 1041 1042class DummyInteractionHandler( unohelper.Base, XInteractionHandler ): 1043 def __init__( self ): 1044 pass 1045 def handle( self, event): 1046 log.debug( "pythonscript: DummyInteractionHandler.handle " + str( event ) ) 1047 1048class DummyProgressHandler( unohelper.Base, XProgressHandler ): 1049 def __init__( self ): 1050 pass 1051 1052 def push( self,status ): 1053 log.debug( "pythonscript: DummyProgressHandler.push " + str( status ) ) 1054 def update( self,status ): 1055 log.debug( "pythonscript: DummyProgressHandler.update " + str( status ) ) 1056 def pop( self ): 1057 log.debug( "pythonscript: DummyProgressHandler.push " + str( event ) ) 1058 1059class CommandEnvironment(unohelper.Base, XCommandEnvironment): 1060 def __init__( self ): 1061 self.progressHandler = DummyProgressHandler() 1062 self.interactionHandler = DummyInteractionHandler() 1063 def getInteractionHandler( self ): 1064 return self.interactionHandler 1065 def getProgressHandler( self ): 1066 return self.progressHandler 1067 1068#maybe useful for debugging purposes 1069#class ModifyListener( unohelper.Base, XModifyListener ): 1070# def __init__( self ): 1071# pass 1072# def modified( self, event ): 1073# log.debug( "pythonscript: ModifyListener.modified " + str( event ) ) 1074# def disposing( self, event ): 1075# log.debug( "pythonscript: ModifyListener.disposing " + str( event ) ) 1076 1077def getModelFromDocUrl(ctx, url): 1078 """Get document model from document url.""" 1079 doc = None 1080 args = ("Local", "Office") 1081 ucb = ctx.getServiceManager().createInstanceWithArgumentsAndContext( 1082 "com.sun.star.ucb.UniversalContentBroker", args, ctx) 1083 identifier = ucb.createContentIdentifier(url) 1084 content = ucb.queryContent(identifier) 1085 p = Property() 1086 p.Name = "DocumentModel" 1087 p.Handle = -1 1088 1089 c = Command() 1090 c.Handle = -1 1091 c.Name = "getPropertyValues" 1092 c.Argument = uno.Any("[]com.sun.star.beans.Property", (p,)) 1093 1094 env = CommandEnvironment() 1095 try: 1096 ret = content.execute(c, 0, env) 1097 doc = ret.getObject(1, None) 1098 except Exception as e: 1099 log.isErrorLevel() and log.error("getModelFromDocUrl: %s" % url) 1100 return doc 1101 1102def mapStorageType2PackageContext( storageType ): 1103 ret = storageType 1104 if( storageType == "share:uno_packages" ): 1105 ret = "shared" 1106 if( storageType == "user:uno_packages" ): 1107 ret = "user" 1108 return ret 1109 1110def getPackageName2PathMap( sfa, storageType ): 1111 ret = {} 1112 packageManagerFactory = uno.getComponentContext().getValueByName( 1113 "/singletons/com.sun.star.deployment.thePackageManagerFactory" ) 1114 packageManager = packageManagerFactory.getPackageManager( 1115 mapStorageType2PackageContext(storageType)) 1116# packageManager.addModifyListener( ModifyListener() ) 1117 log.debug( "pythonscript: getPackageName2PathMap start getDeployedPackages" ) 1118 packages = packageManager.getDeployedPackages( 1119 packageManager.createAbortChannel(), CommandEnvironment( ) ) 1120 log.debug( "pythonscript: getPackageName2PathMap end getDeployedPackages (" + str(len(packages))+")" ) 1121 1122 for i in packages: 1123 log.debug( "inspecting package " + i.Name + "("+i.Identifier.Value+")" ) 1124 transientPathElement = penultimateElement( i.URL ) 1125 j = expandUri( i.URL ) 1126 pathes = getPathesFromPackage( j, sfa ) 1127 if len( pathes ) > 0: 1128 # map package name to url, we need this later 1129 log.isErrorLevel() and log.error( "adding Package " + transientPathElement + " " + str( pathes ) ) 1130 ret[ lastElement( j ) ] = Package( pathes, transientPathElement ) 1131 return ret 1132 1133def penultimateElement( aStr ): 1134 lastSlash = aStr.rindex("/") 1135 penultimateSlash = aStr.rindex("/",0,lastSlash-1) 1136 return aStr[ penultimateSlash+1:lastSlash ] 1137 1138def lastElement( aStr): 1139 return aStr[ aStr.rfind( "/" )+1:len(aStr)] 1140 1141class PackageBrowseNode( unohelper.Base, XBrowseNode, XPropertySet, XInvocation ): 1142 def __init__( self, provCtx, name, rootUrl ): 1143 self.provCtx = provCtx 1144 self.name = name 1145 self.rootUrl = rootUrl 1146 1147 def getName( self ): 1148 return self.name 1149 1150 def getChildNodes( self ): 1151 items = list(self.provCtx.mapPackageName2Path.items()) 1152 browseNodeList = [] 1153 for i in items: 1154 if len( i[1].pathes ) == 1: 1155 browseNodeList.append( 1156 DirBrowseNode( self.provCtx, i[0], i[1].pathes[0], 0 )) 1157 else: 1158 for j in i[1].pathes: 1159 browseNodeList.append( 1160 DirBrowseNode( self.provCtx, i[0]+"."+lastElement(j), j, 0 ) ) 1161 return tuple( browseNodeList ) 1162 1163 def hasChildNodes( self ): 1164 return len( self.mapPackageName2Path ) > 0 1165 1166 def getType( self ): 1167 return CONTAINER 1168 1169 def getScript( self, uri ): 1170 log.debug( "DirBrowseNode getScript " + uri + " invoked" ) 1171 raise IllegalArgumentException( "PackageBrowseNode couldn't instantiate script " + uri , self , 0 ) 1172 1173 # XPropertySet 1174 1175 def getPropertyValue( self, name ): 1176 ret = None 1177 log.debug( "PackageBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) ) 1178 return ret 1179 1180 def setPropertyValue( self, name, value ): 1181 log.debug( "PackageBrowseNode.setPropertyValue " + name + "=" +str( value ) ) 1182 1183 def getPropertySetInfo( self ): 1184 log.debug( "PackageBrowseNode.getPropertySetInfo called" ) 1185 return None 1186 1187 # XInvocation 1188 1189 def getIntrospection( self ): 1190 log.debug( "PackageBrowseNode.getIntrospection() called" ) 1191 return None 1192 1193 def invoke( self, name, params, outparamindex, outparams ): 1194 log.debug( "PackageBrowseNode.invoke called for " + name + "," + str( params ) + "," + str( outparamindex ) + "," + str( outparams ) ) 1195 return None, (), () 1196 1197 def setValue( self, name, value ): 1198 log.debug( "PackageBrowseNode.setValue" ) 1199 return None 1200 1201 def getValue( self, name ): 1202 log.debug( "PackageBrowseNode.getValue" ) 1203 return None 1204 1205 def hasMethod( self, name ): 1206 log.debug( "PackageBrowseNode.hasMethod" ) 1207 return False 1208 1209 def hasProperty( self, name ): 1210 log.debug( "PackageBrowseNode.hasProperty" ) 1211 return False 1212 1213 1214 1215class PythonScript( unohelper.Base, XScript ): 1216 def __init__( self, func, mod ): 1217 self.func = func 1218 self.mod = mod 1219 def invoke(self, args, out, outindex ): 1220 log.debug( "PythonScript.invoke " + str( args ) ) 1221 try: 1222 ret = self.func( *args ) 1223 except UnoException as e: 1224 # UNO Exception continue to fly ... 1225 text = lastException2String() 1226 complete = "Error during invoking function " + \ 1227 str(self.func.__name__) + " in module " + \ 1228 self.mod.__file__ + " (" + text + ")" 1229 log.debug( complete ) 1230 # some people may beat me up for modifying the exception text, 1231 # but otherwise office just shows 1232 # the type name and message text with no more information, 1233 # this is really bad for most users. 1234 e.Message = e.Message + " (" + complete + ")" 1235 raise 1236 except Exception as e: 1237 # General python exception are converted to uno RuntimeException 1238 text = lastException2String() 1239 complete = "Error during invoking function " + \ 1240 str(self.func.__name__) + " in module " + \ 1241 self.mod.__file__ + " (" + text + ")" 1242 log.debug( complete ) 1243 raise RuntimeException( complete , self ) 1244 log.debug( "PythonScript.invoke ret = " + str( ret ) ) 1245 return ret, (), () 1246 1247def expandUri( uri ): 1248 if uri.startswith( "vnd.sun.star.expand:" ): 1249 uri = uri.replace( "vnd.sun.star.expand:", "",1) 1250 uri = uno.getComponentContext().getByName( 1251 "/singletons/com.sun.star.util.theMacroExpander" ).expandMacros( uri ) 1252 if uri.startswith( "file:" ): 1253 uri = uno.absolutize("",uri) # necessary to get rid of .. in uri 1254 return uri 1255 1256#-------------------------------------------------------------- 1257class PythonScriptProvider( unohelper.Base, XBrowseNode, XScriptProvider, XNameContainer, XPropertySet, XInvocation): 1258 def __init__( self, ctx, *args ): 1259 if log.isDebugLevel(): 1260 mystr = "" 1261 for i in args: 1262 if len(mystr) > 0: 1263 mystr = mystr +"," 1264 mystr = mystr + str(i) 1265 log.debug( "Entering PythonScriptProvider.ctor with args " + mystr ) 1266 1267 doc = None 1268 inv = None 1269 storageType = "" 1270 1271 if isinstance(args[0],unicode ): 1272 storageType = args[0] 1273 if storageType.startswith( "vnd.sun.star.tdoc" ): 1274 doc = getModelFromDocUrl(ctx, storageType) 1275 else: 1276 inv = args[0] 1277 try: 1278 doc = inv.ScriptContainer 1279 content = ctx.getServiceManager().createInstanceWithContext( 1280 "com.sun.star.frame.TransientDocumentsDocumentContentFactory", 1281 ctx).createDocumentContent(doc) 1282 storageType = content.getIdentifier().getContentIdentifier() 1283 except Exception as e: 1284 text = lastException2String() 1285 log.error( text ) 1286 1287 isPackage = storageType.endswith( ":uno_packages" ) 1288 1289 try: 1290# urlHelper = ctx.ServiceManager.createInstanceWithArgumentsAndContext( 1291# "com.sun.star.script.provider.ScriptURIHelper", (LANGUAGENAME, storageType), ctx) 1292 urlHelper = MyUriHelper( ctx, storageType ) 1293 log.debug( "got urlHelper " + str( urlHelper ) ) 1294 1295 rootUrl = expandUri( urlHelper.getRootStorageURI() ) 1296 log.debug( storageType + " transformed to " + rootUrl ) 1297 1298 ucbService = "com.sun.star.ucb.SimpleFileAccess" 1299 sfa = ctx.ServiceManager.createInstanceWithContext( ucbService, ctx ) 1300 if not sfa: 1301 log.debug("PythonScriptProvider couldn't instantiate " +ucbService) 1302 raise RuntimeException( 1303 "PythonScriptProvider couldn't instantiate " +ucbService, self) 1304 self.provCtx = ProviderContext( 1305 storageType, sfa, urlHelper, ScriptContext( uno.getComponentContext(), doc, inv ) ) 1306 if isPackage: 1307 mapPackageName2Path = getPackageName2PathMap( sfa, storageType ) 1308 self.provCtx.setPackageAttributes( mapPackageName2Path , rootUrl ) 1309 self.dirBrowseNode = PackageBrowseNode( self.provCtx, LANGUAGENAME, rootUrl ) 1310 else: 1311 self.dirBrowseNode = DirBrowseNode( self.provCtx, LANGUAGENAME, rootUrl, 0 ) 1312 1313 except Exception as e: 1314 text = lastException2String() 1315 log.debug( "PythonScriptProvider could not be instantiated because of : " + text ) 1316 raise e 1317 1318 def getName( self ): 1319 return self.dirBrowseNode.getName() 1320 1321 def getChildNodes( self ): 1322 return self.dirBrowseNode.getChildNodes() 1323 1324 def hasChildNodes( self ): 1325 return self.dirBrowseNode.hasChildNodes() 1326 1327 def getType( self ): 1328 return self.dirBrowseNode.getType() 1329 1330 def getScript( self, uri ): 1331 log.debug( "DirBrowseNode getScript " + uri + " invoked" ) 1332 1333 raise IllegalArgumentException( "DirBrowseNode couldn't instantiate script " + uri , self , 0 ) 1334 1335 def getScript( self, scriptUri ): 1336 try: 1337 log.debug( "getScript " + scriptUri + " invoked") 1338 1339 storageUri = self.provCtx.getStorageUrlFromPersistentUrl( 1340 self.provCtx.uriHelper.getStorageURI(scriptUri) ); 1341 log.debug( "getScript: storageUri = " + storageUri) 1342 fileUri = storageUri[0:storageUri.find( "$" )] 1343 funcName = storageUri[storageUri.find( "$" )+1:len(storageUri)] 1344 1345 mod = self.provCtx.getModuleByUrl( fileUri ) 1346 log.debug( " got mod " + str(mod) ) 1347 1348 func = mod.__dict__[ funcName ] 1349 1350 log.debug( "got func " + str( func ) ) 1351 return PythonScript( func, mod ) 1352 except Exception as e: 1353 text = lastException2String() 1354 log.error( text ) 1355 raise ScriptFrameworkErrorException( text, self, scriptUri, LANGUAGENAME, 0 ) 1356 1357 # XPropertySet 1358 1359 def getPropertyValue( self, name ): 1360 return self.dirBrowseNode.getPropertyValue( name ) 1361 1362 def setPropertyValue( self, name, value ): 1363 return self.dirBrowseNode.setPropertyValue( name, value ) 1364 1365 def getPropertySetInfo( self ): 1366 return self.dirBrowseNode.getPropertySetInfo() 1367 1368 # XInvocation 1369 1370 def getIntrospection( self ): 1371 return self.dirBrowseNode.getIntrospection() 1372 1373 def invoke( self, name, params, outparamindex, outparams ): 1374 return self.dirBrowseNode.invoke( name, params, outparamindex, outparams) 1375 1376 def setValue( self, name, value ): 1377 return self.dirBrowseNode.setValue( name, value ) 1378 1379 def getValue( self, name ): 1380 return self.dirBrowseNode.getValue( name ) 1381 1382 def hasMethod( self, name ): 1383 return self.dirBrowseNode.hasMethod( name ) 1384 1385 def hasProperty( self, name ): 1386 return self.dirBrowseNode.hasProperty( name ) 1387 1388 # XServiceInfo 1389 def getSupportedServices( self ): 1390 return g_ImplementationHelper.getSupportedServices(g_implName) 1391 1392 def supportsService( self, ServiceName ): 1393 return g_ImplementationHelper.supportsService( g_implName, ServiceName ) 1394 1395 def getImplementationName(self): 1396 return g_implName 1397 1398 def getByName( self, name ): 1399 log.debug( "getByName called" + str( name )) 1400 return None 1401 1402 1403 def getElementNames( self ): 1404 log.debug( "getElementNames called") 1405 return () 1406 1407 def hasByName( self, name ): 1408 try: 1409 log.debug( "hasByName called " + str( name )) 1410 uri = expandUri(name) 1411 ret = self.provCtx.isUrlInPackage( uri ) 1412 log.debug( "hasByName " + uri + " " +str( ret ) ) 1413 return ret 1414 except Exception as e: 1415 text = lastException2String() 1416 log.debug( "Error in hasByName:" + text ) 1417 return False 1418 1419 def removeByName( self, name ): 1420 log.debug( "removeByName called" + str( name )) 1421 uri = expandUri( name ) 1422 if self.provCtx.isUrlInPackage( uri ): 1423 self.provCtx.removePackageByUrl( uri ) 1424 else: 1425 log.debug( "removeByName unknown uri " + str( name ) + ", ignoring" ) 1426 raise NoSuchElementException( uri + "is not in package" , self ) 1427 log.debug( "removeByName called" + str( uri ) + " successful" ) 1428 1429 def insertByName( self, name, value ): 1430 log.debug( "insertByName called " + str( name ) + " " + str( value )) 1431 uri = expandUri( name ) 1432 if isPyFileInPath( self.provCtx.sfa, uri ): 1433 self.provCtx.addPackageByUrl( uri ) 1434 else: 1435 # package is no python package ... 1436 log.debug( "insertByName: no python files in " + str( uri ) + ", ignoring" ) 1437 raise IllegalArgumentException( uri + " does not contain .py files", self, 1 ) 1438 log.debug( "insertByName called " + str( uri ) + " successful" ) 1439 1440 def replaceByName( self, name, value ): 1441 log.debug( "replaceByName called " + str( name ) + " " + str( value )) 1442 removeByName( name ) 1443 insertByName( name ) 1444 log.debug( "replaceByName called" + str( uri ) + " successful" ) 1445 1446 def getElementType( self ): 1447 log.debug( "getElementType called" ) 1448 return uno.getTypeByName( "void" ) 1449 1450 def hasElements( self ): 1451 log.debug( "hasElements got called") 1452 return False 1453 1454g_ImplementationHelper.addImplementation( \ 1455 PythonScriptProvider,g_implName, \ 1456 ("com.sun.star.script.provider.LanguageScriptProvider", 1457 "com.sun.star.script.provider.ScriptProviderFor"+ LANGUAGENAME,),) 1458 1459 1460log.debug( "pythonscript finished initializing" ) 1461