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