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