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("utf-8")) 671 copyUrl = self.uri() + ".orig" 672 self.provCtx.sfa.move( self.uri(), copyUrl ) 673 log.debug( "Saving Python macro to URI " + self.uri() ) 674 self.provCtx.sfa.writeFile( self.uri(), BytesInputStream( toWrite.value ) ) 675 self.provCtx.sfa.kill( copyUrl ) 676 except Exception as e: 677 # TODO: add an error box here ! 678 log.error( lastException2String() ) 679 680 681 def setValue( self, name, value ): 682 return None 683 684 def getValue( self, name ): 685 return None 686 687 def hasMethod( self, name ): 688 return False 689 690 def hasProperty( self, name ): 691 return False 692 693 694#------------------------------------------------------- 695class FileBrowseNode( unohelper.Base, XBrowseNode, XPropertySet, XInvocation, XActionListener ): 696 def __init__( self, provCtx, parent, name ): 697 self.provCtx = provCtx 698 self.parent = parent 699 self.name = name 700 self.funcnames = None 701 702 def uri( self ): 703 return self.parent.rootUrl + "/" + self.name + ".py" 704 705 def getName( self ): 706 return self.name 707 708 def getChildNodes(self): 709 ret = () 710 try: 711 self.funcnames = self.provCtx.getFuncsByUrl( self.uri() ) 712 713 scriptNodeList = [] 714 for i in self.funcnames: 715 scriptNodeList.append( 716 ScriptBrowseNode( 717 self.provCtx, self, self.name, i )) 718 ret = tuple( scriptNodeList ) 719 except Exception as e: 720 text = lastException2String() 721 log.error( "FileBrowseNode.getChildNodes error while evaluating " + self.uri() + ":" + text ) 722 raise 723 return ret 724 725 def hasChildNodes(self): 726 try: 727 return len(self.getChildNodes()) > 0 728 except Exception as e: 729 return False 730 731 def getType( self): 732 return CONTAINER 733 734 # XPropertySet 735 736 def getPropertyValue( self, name ): 737 ret = None 738 try: 739 if name == "Editable": 740 ret = not self.provCtx.sfa.isReadOnly( self.uri() ) 741 elif name == "Deletable": 742 ret = not self.provCtx.sfa.isReadOnly( self.uri() ) 743 elif name == "Renamable": 744 ret = not self.provCtx.sfa.isReadOnly( self.uri() ) 745 746 log.debug( "FileBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) ) 747 except Exception as e: 748 log.error( "FileBrowseNode.getPropertyValue error " + lastException2String()) 749 raise 750 751 return ret 752 753 def setPropertyValue( self, name, value ): 754 log.debug( "FileBrowseNode.setPropertyValue called " + name + "=" +str(value ) ) 755 756 def getPropertySetInfo( self ): 757 log.debug( "FileBrowseNode.getPropertySetInfo called " ) 758 return None 759 760 # XInvocation 761 762 def getIntrospection( self ): 763 log.debug( "FileBrowseNode.getIntrospection() called" ) 764 return None 765 766 def invoke( self, name, params, outparamindex, outparams ): 767 log.debug("FileBrowseNode.invoke called for " + name + "," + str(params) + "," + str(outparamindex) + "," + str(outparams)) 768 try: 769 if name == "Editable": 770 ctx = self.provCtx.scriptContext.getComponentContext() 771 772 self.editor = createEditorDialog( ctx ) 773 774 code = readTextFromStream(self.provCtx.sfa.openFileRead(self.uri())) 775 code = ensureSourceState( code ) 776 self.editor.getControl("EditorTextField").setText(code) 777 778 self.editor.getControl("RunButton").setActionCommand("Run") 779 self.editor.getControl("RunButton").addActionListener(self) 780 self.editor.getControl("SaveButton").setActionCommand("Save") 781 self.editor.getControl("SaveButton").addActionListener(self) 782 783 self.editor.execute() 784 elif name == "Deletable": 785 self.provCtx.sfa.kill( self.uri() ) 786 return True, (), () 787 elif name == "Renamable": 788 if params is None or not params: 789 raise IllegalArgumentException( "invoke with Creatable needs the name in params" ) 790 newUri = self.parent.rootUrl + "/" + params[0] + ".py" 791 self.provCtx.sfa.move( self.uri(), newUri ) 792 self.name = params[0] 793 return self, (), () 794 except Exception as e: 795 log.error( "FileBrowseNode.invoke error " + lastException2String() ) 796 raise 797 return None, (), () 798 799 def setValue( self, name, value ): 800 return None 801 802 def getValue( self, name ): 803 log.debug( "FileBrowseNode.getValue() called" ) 804 return None 805 806 def hasMethod( self, name ): 807 return False 808 809 def hasProperty( self, name ): 810 return False 811 812 # XActionListener 813 814 def actionPerformed( self, event ): 815 try: 816 if event.ActionCommand == "Run": 817 code = self.editor.getControl("EditorTextField").getText() 818 code = ensureSourceState( code ) 819 mod = imp.new_module("ooo_script_framework") 820 mod.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.provCtx.scriptContext 821 exec(code, mod.__dict__) 822 values = mod.__dict__.get( CALLABLE_CONTAINER_NAME , None ) 823 if not values: 824 values = list(mod.__dict__.values()) 825 826 for i in values: 827 if isScript( i ): 828 i() 829 break 830 831 elif event.ActionCommand == "Save": 832 toWrite = uno.ByteSequence( 833 self.editor.getControl("EditorTextField").getText().encode("utf-8")) 834 copyUrl = self.uri() + ".orig" 835 self.provCtx.sfa.move( self.uri(), copyUrl ) 836 log.debug( "Saving Python macro to URI " + self.uri() ) 837 self.provCtx.sfa.writeFile( self.uri(), BytesInputStream( toWrite.value ) ) 838 self.provCtx.sfa.kill( copyUrl ) 839 except Exception as e: 840 # TODO: add an error box here ! 841 log.error( lastException2String() ) 842 843 844class DirBrowseNode( unohelper.Base, XBrowseNode, XPropertySet, XInvocation ): 845 def __init__( self, provCtx, name, rootUrl, depth ): 846 self.provCtx = provCtx 847 self.name = name 848 self.rootUrl = rootUrl 849 self.depth = depth 850 log.debug( "DirBrowseNode constructor for " + name + "," + rootUrl ) 851 852 def getName( self ): 853 return self.name 854 855 def getChildNodes( self ): 856 try: 857 log.debug( "DirBrowseNode.getChildNodes called for " + self.rootUrl ) 858 contents = self.provCtx.sfa.getFolderContents( self.rootUrl, True ) 859 browseNodeList = [] 860 for i in contents: 861 if i.endswith( ".py" ): 862 log.debug( "adding filenode " + i ) 863 browseNodeList.append( 864 FileBrowseNode( self.provCtx, self, i[i.rfind("/")+1:len(i)-3] ) ) 865 elif self.provCtx.sfa.isFolder( i ) and not i.endswith("/pythonpath"): 866 log.debug( "adding DirBrowseNode " + i ) 867 browseNodeList.append( 868 DirBrowseNode( self.provCtx, i[i.rfind("/")+1:len(i)], i, self.depth + 1 ) ) 869 return tuple( browseNodeList ) 870 except Exception as e: 871 text = lastException2String() 872 log.error( "DirBrowseNode error: " + str(e) + " while evaluating " + self.rootUrl) 873 log.error( text) 874 return () 875 876 def hasChildNodes( self ): 877 return True 878 879 def getType( self ): 880 return CONTAINER 881 882 # XScriptProvider 883 884 def getScript( self, uri ): 885 log.debug( "DirBrowseNode getScript " + uri + " invoked" ) 886 raise IllegalArgumentException( "DirBrowseNode couldn't instantiate script " + uri , self , 0 ) 887 888 # XPropertySet 889 890 def getPropertyValue( self, name ): 891 ret = None 892 try: 893 if name == "Creatable": 894 ret = True 895 elif name == "Deletable": 896 ret = self.depth > 0 and not self.provCtx.sfa.isReadOnly( self.rootUrl ) 897 elif name == "Renamable": 898 ret = self.depth > 0 and not self.provCtx.sfa.isReadOnly( self.rootUrl ) 899 900 log.debug( "DirBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) ) 901 except Exception as e: 902 log.error( "DirBrowseNode.getPropertyValue error " + lastException2String()) 903 raise 904 905 return ret 906 907 def setPropertyValue( self, name, value ): 908 log.debug( "DirBrowseNode.setPropertyValue called " + name + "=" +str(value ) ) 909 910 def getPropertySetInfo( self ): 911 log.debug( "DirBrowseNode.getPropertySetInfo called " ) 912 return None 913 914 # XInvocation 915 916 def getIntrospection( self ): 917 log.debug( "DirBrowseNode.getIntrospection() called" ) 918 return None 919 920 def invoke( self, name, params, outparamindex, outparams ): 921 log.debug("DirBrowseNode.invoke called for " + name + "," + str(params) + "," + str(outparamindex) + "," + str(outparams)) 922 try: 923 if name == "Creatable": 924 if params is None or not params: 925 raise IllegalArgumentException( "invoke with Creatable needs the name in params" ) 926 if self.depth == 0: 927 subFolderUrl = self.rootUrl + "/" + params[0] 928 self.provCtx.sfa.createFolder( subFolderUrl ) 929 childNode = DirBrowseNode( self.provCtx, subFolderUrl[subFolderUrl.rfind("/")+1:len(subFolderUrl)], subFolderUrl, self.depth + 1 ) 930 return childNode, (), () 931 else: 932 scriptUrl = self.rootUrl + "/" + params[0] + ".py" 933 # Creates an empty file 934 self.provCtx.sfa.writeFile( scriptUrl, EmptyInputStream() ) 935 childNode = FileBrowseNode( self.provCtx, self, params[0] ) 936 return childNode, (), () 937 elif name == "Deletable": 938 self.provCtx.sfa.kill( self.rootUrl ) 939 return True, (), () 940 elif name == "Renamable": 941 if params is None or not params: 942 raise IllegalArgumentException( "invoke with Renamable needs the name in params" ) 943 newUrl = self.rootUrl[0:self.rootUrl.rfind("/")+1] + params[0] 944 self.provCtx.sfa.move( self.rootUrl, newUrl ) 945 self.rootUrl = newUrl 946 self.name = params[0] 947 return self, (), () 948 except Exception as e: 949 log.error( "DirBrowseNode.invoke error: " + lastException2String()) 950 raise 951 return None, (), () 952 953 def setValue( self, name, value ): 954 return None 955 956 def getValue( self, name ): 957 log.debug( "DirBrowseNode.getValue() called" ) 958 return None 959 960 def hasMethod( self, name ): 961 return False 962 963 def hasProperty( self, name ): 964 return False 965 966 967class ManifestHandler( XDocumentHandler, unohelper.Base ): 968 def __init__( self, rootUrl ): 969 self.rootUrl = rootUrl 970 971 def startDocument( self ): 972 self.urlList = [] 973 974 def endDocument( self ): 975 pass 976 977 def startElement( self , name, attlist): 978 if name == "manifest:file-entry": 979 if attlist.getValueByName( "manifest:media-type" ) == "application/vnd.sun.star.framework-script": 980 self.urlList.append( 981 self.rootUrl + "/" + attlist.getValueByName( "manifest:full-path" ) ) 982 983 def endElement( self, name ): 984 pass 985 986 def characters ( self, chars ): 987 pass 988 989 def ignoreableWhitespace( self, chars ): 990 pass 991 992 def setDocumentLocator( self, locator ): 993 pass 994 995def isPyFileInPath( sfa, path ): 996 ret = False 997 contents = sfa.getFolderContents( path, True ) 998 for i in contents: 999 if sfa.isFolder(i): 1000 ret = isPyFileInPath(sfa,i) 1001 else: 1002 if i.endswith(".py"): 1003 ret = True 1004 if ret: 1005 break 1006 return ret 1007 1008# extracts META-INF directory from 1009def getPathesFromPackage( rootUrl, sfa ): 1010 ret = () 1011 try: 1012 fileUrl = rootUrl + "/META-INF/manifest.xml" 1013 inputStream = sfa.openFileRead( fileUrl ) 1014 parser = uno.getComponentContext().ServiceManager.createInstance( "com.sun.star.xml.sax.Parser" ) 1015 handler = ManifestHandler( rootUrl ) 1016 parser.setDocumentHandler( handler ) 1017 parser.parseStream( InputSource( inputStream , "", fileUrl, fileUrl ) ) 1018 for i in tuple(handler.urlList): 1019 if not isPyFileInPath( sfa, i ): 1020 handler.urlList.remove(i) 1021 ret = tuple( handler.urlList ) 1022 except UnoException as e: 1023 text = lastException2String() 1024 log.debug( "getPathesFromPackage " + fileUrl + " Exception: " +text ) 1025 pass 1026 return ret 1027 1028 1029class Package: 1030 def __init__( self, pathes, transientPathElement ): 1031 self.pathes = pathes 1032 self.transientPathElement = transientPathElement 1033 1034class DummyInteractionHandler( unohelper.Base, XInteractionHandler ): 1035 def __init__( self ): 1036 pass 1037 def handle( self, event): 1038 log.debug( "pythonscript: DummyInteractionHandler.handle " + str( event ) ) 1039 1040class DummyProgressHandler( unohelper.Base, XProgressHandler ): 1041 def __init__( self ): 1042 pass 1043 1044 def push( self,status ): 1045 log.debug( "pythonscript: DummyProgressHandler.push " + str( status ) ) 1046 def update( self,status ): 1047 log.debug( "pythonscript: DummyProgressHandler.update " + str( status ) ) 1048 def pop( self ): 1049 log.debug( "pythonscript: DummyProgressHandler.push " + str( event ) ) 1050 1051class CommandEnvironment(unohelper.Base, XCommandEnvironment): 1052 def __init__( self ): 1053 self.progressHandler = DummyProgressHandler() 1054 self.interactionHandler = DummyInteractionHandler() 1055 def getInteractionHandler( self ): 1056 return self.interactionHandler 1057 def getProgressHandler( self ): 1058 return self.progressHandler 1059 1060#maybe useful for debugging purposes 1061#class ModifyListener( unohelper.Base, XModifyListener ): 1062# def __init__( self ): 1063# pass 1064# def modified( self, event ): 1065# log.debug( "pythonscript: ModifyListener.modified " + str( event ) ) 1066# def disposing( self, event ): 1067# log.debug( "pythonscript: ModifyListener.disposing " + str( event ) ) 1068 1069def getModelFromDocUrl(ctx, url): 1070 """Get document model from document url.""" 1071 doc = None 1072 args = ("Local", "Office") 1073 ucb = ctx.getServiceManager().createInstanceWithArgumentsAndContext( 1074 "com.sun.star.ucb.UniversalContentBroker", args, ctx) 1075 identifier = ucb.createContentIdentifier(url) 1076 content = ucb.queryContent(identifier) 1077 p = Property() 1078 p.Name = "DocumentModel" 1079 p.Handle = -1 1080 1081 c = Command() 1082 c.Handle = -1 1083 c.Name = "getPropertyValues" 1084 c.Argument = uno.Any("[]com.sun.star.beans.Property", (p,)) 1085 1086 env = CommandEnvironment() 1087 try: 1088 ret = content.execute(c, 0, env) 1089 doc = ret.getObject(1, None) 1090 except Exception as e: 1091 log.isErrorLevel() and log.error("getModelFromDocUrl: %s" % url) 1092 return doc 1093 1094def mapStorageType2PackageContext( storageType ): 1095 ret = storageType 1096 if( storageType == "share:uno_packages" ): 1097 ret = "shared" 1098 if( storageType == "user:uno_packages" ): 1099 ret = "user" 1100 return ret 1101 1102def getPackageName2PathMap( sfa, storageType ): 1103 ret = {} 1104 packageManagerFactory = uno.getComponentContext().getValueByName( 1105 "/singletons/com.sun.star.deployment.thePackageManagerFactory" ) 1106 packageManager = packageManagerFactory.getPackageManager( 1107 mapStorageType2PackageContext(storageType)) 1108# packageManager.addModifyListener( ModifyListener() ) 1109 log.debug( "pythonscript: getPackageName2PathMap start getDeployedPackages" ) 1110 packages = packageManager.getDeployedPackages( 1111 packageManager.createAbortChannel(), CommandEnvironment( ) ) 1112 log.debug( "pythonscript: getPackageName2PathMap end getDeployedPackages (" + str(len(packages))+")" ) 1113 1114 for i in packages: 1115 log.debug( "inspecting package " + i.Name + "("+i.Identifier.Value+")" ) 1116 transientPathElement = penultimateElement( i.URL ) 1117 j = expandUri( i.URL ) 1118 pathes = getPathesFromPackage( j, sfa ) 1119 if len( pathes ) > 0: 1120 # map package name to url, we need this later 1121 log.isErrorLevel() and log.error( "adding Package " + transientPathElement + " " + str( pathes ) ) 1122 ret[ lastElement( j ) ] = Package( pathes, transientPathElement ) 1123 return ret 1124 1125def penultimateElement( aStr ): 1126 lastSlash = aStr.rindex("/") 1127 penultimateSlash = aStr.rindex("/",0,lastSlash-1) 1128 return aStr[ penultimateSlash+1:lastSlash ] 1129 1130def lastElement( aStr): 1131 return aStr[ aStr.rfind( "/" )+1:len(aStr)] 1132 1133class PackageBrowseNode( unohelper.Base, XBrowseNode, XPropertySet, XInvocation ): 1134 def __init__( self, provCtx, name, rootUrl ): 1135 self.provCtx = provCtx 1136 self.name = name 1137 self.rootUrl = rootUrl 1138 1139 def getName( self ): 1140 return self.name 1141 1142 def getChildNodes( self ): 1143 items = list(self.provCtx.mapPackageName2Path.items()) 1144 browseNodeList = [] 1145 for i in items: 1146 if len( i[1].pathes ) == 1: 1147 browseNodeList.append( 1148 DirBrowseNode( self.provCtx, i[0], i[1].pathes[0], 0 )) 1149 else: 1150 for j in i[1].pathes: 1151 browseNodeList.append( 1152 DirBrowseNode( self.provCtx, i[0]+"."+lastElement(j), j, 0 ) ) 1153 return tuple( browseNodeList ) 1154 1155 def hasChildNodes( self ): 1156 return len( self.mapPackageName2Path ) > 0 1157 1158 def getType( self ): 1159 return CONTAINER 1160 1161 def getScript( self, uri ): 1162 log.debug( "DirBrowseNode getScript " + uri + " invoked" ) 1163 raise IllegalArgumentException( "PackageBrowseNode couldn't instantiate script " + uri , self , 0 ) 1164 1165 # XPropertySet 1166 1167 def getPropertyValue( self, name ): 1168 ret = None 1169 log.debug( "PackageBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) ) 1170 return ret 1171 1172 def setPropertyValue( self, name, value ): 1173 log.debug( "PackageBrowseNode.setPropertyValue " + name + "=" +str( value ) ) 1174 1175 def getPropertySetInfo( self ): 1176 log.debug( "PackageBrowseNode.getPropertySetInfo called" ) 1177 return None 1178 1179 # XInvocation 1180 1181 def getIntrospection( self ): 1182 log.debug( "PackageBrowseNode.getIntrospection() called" ) 1183 return None 1184 1185 def invoke( self, name, params, outparamindex, outparams ): 1186 log.debug( "PackageBrowseNode.invoke called for " + name + "," + str( params ) + "," + str( outparamindex ) + "," + str( outparams ) ) 1187 return None, (), () 1188 1189 def setValue( self, name, value ): 1190 log.debug( "PackageBrowseNode.setValue" ) 1191 return None 1192 1193 def getValue( self, name ): 1194 log.debug( "PackageBrowseNode.getValue" ) 1195 return None 1196 1197 def hasMethod( self, name ): 1198 log.debug( "PackageBrowseNode.hasMethod" ) 1199 return False 1200 1201 def hasProperty( self, name ): 1202 log.debug( "PackageBrowseNode.hasProperty" ) 1203 return False 1204 1205 1206 1207class PythonScript( unohelper.Base, XScript ): 1208 def __init__( self, func, mod ): 1209 self.func = func 1210 self.mod = mod 1211 def invoke(self, args, out, outindex ): 1212 log.debug( "PythonScript.invoke " + str( args ) ) 1213 try: 1214 ret = self.func( *args ) 1215 except UnoException as e: 1216 # UNO Exception continue to fly ... 1217 text = lastException2String() 1218 complete = "Error during invoking function " + \ 1219 str(self.func.__name__) + " in module " + \ 1220 self.mod.__file__ + " (" + text + ")" 1221 log.debug( complete ) 1222 # some people may beat me up for modifying the exception text, 1223 # but otherwise office just shows 1224 # the type name and message text with no more information, 1225 # this is really bad for most users. 1226 e.Message = e.Message + " (" + complete + ")" 1227 raise 1228 except Exception as e: 1229 # General python exception are converted to uno RuntimeException 1230 text = lastException2String() 1231 complete = "Error during invoking function " + \ 1232 str(self.func.__name__) + " in module " + \ 1233 self.mod.__file__ + " (" + text + ")" 1234 log.debug( complete ) 1235 raise RuntimeException( complete , self ) 1236 log.debug( "PythonScript.invoke ret = " + str( ret ) ) 1237 return ret, (), () 1238 1239def expandUri( uri ): 1240 if uri.startswith( "vnd.sun.star.expand:" ): 1241 uri = uri.replace( "vnd.sun.star.expand:", "",1) 1242 uri = uno.getComponentContext().getByName( 1243 "/singletons/com.sun.star.util.theMacroExpander" ).expandMacros( uri ) 1244 if uri.startswith( "file:" ): 1245 uri = uno.absolutize("",uri) # necessary to get rid of .. in uri 1246 return uri 1247 1248#-------------------------------------------------------------- 1249class PythonScriptProvider( unohelper.Base, XBrowseNode, XScriptProvider, XNameContainer, XPropertySet, XInvocation): 1250 def __init__( self, ctx, *args ): 1251 if log.isDebugLevel(): 1252 mystr = "" 1253 for i in args: 1254 if len(mystr) > 0: 1255 mystr = mystr +"," 1256 mystr = mystr + str(i) 1257 log.debug( "Entering PythonScriptProvider.ctor with args " + mystr ) 1258 1259 doc = None 1260 inv = None 1261 storageType = "" 1262 1263 if isinstance(args[0],unicode ): 1264 storageType = args[0] 1265 if storageType.startswith( "vnd.sun.star.tdoc" ): 1266 doc = getModelFromDocUrl(ctx, storageType) 1267 else: 1268 inv = args[0] 1269 try: 1270 doc = inv.ScriptContainer 1271 content = ctx.getServiceManager().createInstanceWithContext( 1272 "com.sun.star.frame.TransientDocumentsDocumentContentFactory", 1273 ctx).createDocumentContent(doc) 1274 storageType = content.getIdentifier().getContentIdentifier() 1275 except Exception as e: 1276 text = lastException2String() 1277 log.error( text ) 1278 1279 isPackage = storageType.endswith( ":uno_packages" ) 1280 1281 try: 1282# urlHelper = ctx.ServiceManager.createInstanceWithArgumentsAndContext( 1283# "com.sun.star.script.provider.ScriptURIHelper", (LANGUAGENAME, storageType), ctx) 1284 urlHelper = MyUriHelper( ctx, storageType ) 1285 log.debug( "got urlHelper " + str( urlHelper ) ) 1286 1287 rootUrl = expandUri( urlHelper.getRootStorageURI() ) 1288 log.debug( storageType + " transformed to " + rootUrl ) 1289 1290 ucbService = "com.sun.star.ucb.SimpleFileAccess" 1291 sfa = ctx.ServiceManager.createInstanceWithContext( ucbService, ctx ) 1292 if not sfa: 1293 log.debug("PythonScriptProvider couldn't instantiate " +ucbService) 1294 raise RuntimeException( 1295 "PythonScriptProvider couldn't instantiate " +ucbService, self) 1296 self.provCtx = ProviderContext( 1297 storageType, sfa, urlHelper, ScriptContext( uno.getComponentContext(), doc, inv ) ) 1298 if isPackage: 1299 mapPackageName2Path = getPackageName2PathMap( sfa, storageType ) 1300 self.provCtx.setPackageAttributes( mapPackageName2Path , rootUrl ) 1301 self.dirBrowseNode = PackageBrowseNode( self.provCtx, LANGUAGENAME, rootUrl ) 1302 else: 1303 self.dirBrowseNode = DirBrowseNode( self.provCtx, LANGUAGENAME, rootUrl, 0 ) 1304 1305 except Exception as e: 1306 text = lastException2String() 1307 log.debug( "PythonScriptProvider could not be instantiated because of : " + text ) 1308 raise e 1309 1310 def getName( self ): 1311 return self.dirBrowseNode.getName() 1312 1313 def getChildNodes( self ): 1314 return self.dirBrowseNode.getChildNodes() 1315 1316 def hasChildNodes( self ): 1317 return self.dirBrowseNode.hasChildNodes() 1318 1319 def getType( self ): 1320 return self.dirBrowseNode.getType() 1321 1322 def getScript( self, uri ): 1323 log.debug( "DirBrowseNode getScript " + uri + " invoked" ) 1324 1325 raise IllegalArgumentException( "DirBrowseNode couldn't instantiate script " + uri , self , 0 ) 1326 1327 def getScript( self, scriptUri ): 1328 try: 1329 log.debug( "getScript " + scriptUri + " invoked") 1330 1331 storageUri = self.provCtx.getStorageUrlFromPersistentUrl( 1332 self.provCtx.uriHelper.getStorageURI(scriptUri) ); 1333 log.debug( "getScript: storageUri = " + storageUri) 1334 fileUri = storageUri[0:storageUri.find( "$" )] 1335 funcName = storageUri[storageUri.find( "$" )+1:len(storageUri)] 1336 1337 mod = self.provCtx.getModuleByUrl( fileUri ) 1338 log.debug( " got mod " + str(mod) ) 1339 1340 func = mod.__dict__[ funcName ] 1341 1342 log.debug( "got func " + str( func ) ) 1343 return PythonScript( func, mod ) 1344 except Exception as e: 1345 text = lastException2String() 1346 log.error( text ) 1347 raise ScriptFrameworkErrorException( text, self, scriptUri, LANGUAGENAME, 0 ) 1348 1349 # XPropertySet 1350 1351 def getPropertyValue( self, name ): 1352 return self.dirBrowseNode.getPropertyValue( name ) 1353 1354 def setPropertyValue( self, name, value ): 1355 return self.dirBrowseNode.setPropertyValue( name, value ) 1356 1357 def getPropertySetInfo( self ): 1358 return self.dirBrowseNode.getPropertySetInfo() 1359 1360 # XInvocation 1361 1362 def getIntrospection( self ): 1363 return self.dirBrowseNode.getIntrospection() 1364 1365 def invoke( self, name, params, outparamindex, outparams ): 1366 return self.dirBrowseNode.invoke( name, params, outparamindex, outparams) 1367 1368 def setValue( self, name, value ): 1369 return self.dirBrowseNode.setValue( name, value ) 1370 1371 def getValue( self, name ): 1372 return self.dirBrowseNode.getValue( name ) 1373 1374 def hasMethod( self, name ): 1375 return self.dirBrowseNode.hasMethod( name ) 1376 1377 def hasProperty( self, name ): 1378 return self.dirBrowseNode.hasProperty( name ) 1379 1380 # XServiceInfo 1381 def getSupportedServices( self ): 1382 return g_ImplementationHelper.getSupportedServices(g_implName) 1383 1384 def supportsService( self, ServiceName ): 1385 return g_ImplementationHelper.supportsService( g_implName, ServiceName ) 1386 1387 def getImplementationName(self): 1388 return g_implName 1389 1390 def getByName( self, name ): 1391 log.debug( "getByName called" + str( name )) 1392 return None 1393 1394 1395 def getElementNames( self ): 1396 log.debug( "getElementNames called") 1397 return () 1398 1399 def hasByName( self, name ): 1400 try: 1401 log.debug( "hasByName called " + str( name )) 1402 uri = expandUri(name) 1403 ret = self.provCtx.isUrlInPackage( uri ) 1404 log.debug( "hasByName " + uri + " " +str( ret ) ) 1405 return ret 1406 except Exception as e: 1407 text = lastException2String() 1408 log.debug( "Error in hasByName:" + text ) 1409 return False 1410 1411 def removeByName( self, name ): 1412 log.debug( "removeByName called" + str( name )) 1413 uri = expandUri( name ) 1414 if self.provCtx.isUrlInPackage( uri ): 1415 self.provCtx.removePackageByUrl( uri ) 1416 else: 1417 log.debug( "removeByName unknown uri " + str( name ) + ", ignoring" ) 1418 raise NoSuchElementException( uri + "is not in package" , self ) 1419 log.debug( "removeByName called" + str( uri ) + " successful" ) 1420 1421 def insertByName( self, name, value ): 1422 log.debug( "insertByName called " + str( name ) + " " + str( value )) 1423 uri = expandUri( name ) 1424 if isPyFileInPath( self.provCtx.sfa, uri ): 1425 self.provCtx.addPackageByUrl( uri ) 1426 else: 1427 # package is no python package ... 1428 log.debug( "insertByName: no python files in " + str( uri ) + ", ignoring" ) 1429 raise IllegalArgumentException( uri + " does not contain .py files", self, 1 ) 1430 log.debug( "insertByName called " + str( uri ) + " successful" ) 1431 1432 def replaceByName( self, name, value ): 1433 log.debug( "replaceByName called " + str( name ) + " " + str( value )) 1434 removeByName( name ) 1435 insertByName( name ) 1436 log.debug( "replaceByName called" + str( uri ) + " successful" ) 1437 1438 def getElementType( self ): 1439 log.debug( "getElementType called" ) 1440 return uno.getTypeByName( "void" ) 1441 1442 def hasElements( self ): 1443 log.debug( "hasElements got called") 1444 return False 1445 1446g_ImplementationHelper.addImplementation( \ 1447 PythonScriptProvider,g_implName, \ 1448 ("com.sun.star.script.provider.LanguageScriptProvider", 1449 "com.sun.star.script.provider.ScriptProviderFor"+ LANGUAGENAME,),) 1450 1451 1452log.debug( "pythonscript finished initializing" ) 1453