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 return uni.encode( sys.getfilesystemencoding()) 59 60def lastException2String(): 61 (excType,excInstance,excTraceback) = sys.exc_info() 62 ret = str(excType) + ": "+str(excInstance) + "\n" + \ 63 uno._uno_extract_printable_stacktrace( excTraceback ) 64 return ret 65 66def logLevel2String( level ): 67 ret = " NONE" 68 if level == LogLevel.ERROR: 69 ret = "ERROR" 70 elif level >= LogLevel.DEBUG: 71 ret = "DEBUG" 72 return ret 73 74def getLogTarget(): 75 ret = sys.stdout 76 if not LOG_STDOUT: 77 try: 78 pathSubst = uno.getComponentContext().ServiceManager.createInstance( 79 "com.sun.star.util.PathSubstitution" ) 80 userInstallation = pathSubst.getSubstituteVariableValue( "user" ) 81 if len( userInstallation ) > 0: 82 systemPath = uno.fileUrlToSystemPath( userInstallation + "/Scripts/python/log.txt" ) 83 ret = file( systemPath , "a" ) 84 except Exception as e: 85 print("Exception during creation of pythonscript logfile: "+ lastException2String() + "\n, delagating log to stdout\n") 86 return ret 87 88class Logger(LogLevel): 89 def __init__(self , target ): 90 self.target = target 91 92 def isDebugLevel( self ): 93 return self.use >= self.DEBUG 94 95 def debug( self, msg ): 96 if self.isDebugLevel(): 97 self.log( self.DEBUG, msg ) 98 99 def isErrorLevel( self ): 100 return self.use >= self.ERROR 101 102 def error( self, msg ): 103 if self.isErrorLevel(): 104 self.log( self.ERROR, msg ) 105 106 def log( self, level, msg ): 107 if self.use >= level: 108 try: 109 self.target.write( 110 time.asctime() + 111 " [" + 112 logLevel2String( level ) + 113 "] " + 114 encfile(msg) + 115 "\n" ) 116 self.target.flush() 117 except Exception as e: 118 print("Error during writing to stdout: " +lastException2String() + "\n") 119 120log = Logger( getLogTarget() ) 121 122log.debug( "pythonscript loading" ) 123 124#from com.sun.star.lang import typeOfXServiceInfo, typeOfXTypeProvider 125from com.sun.star.uno import RuntimeException 126from com.sun.star.lang import XServiceInfo 127from com.sun.star.io import IOException, XInputStream 128from com.sun.star.ucb import CommandAbortedException, XCommandEnvironment, XProgressHandler, Command 129from com.sun.star.task import XInteractionHandler 130from com.sun.star.beans import XPropertySet, Property 131from com.sun.star.container import XNameContainer 132from com.sun.star.xml.sax import XDocumentHandler, InputSource 133from com.sun.star.uno import Exception as UnoException 134from com.sun.star.script import XInvocation 135from com.sun.star.awt import XActionListener, FontDescriptor 136from com.sun.star.awt.FontPitch import FIXED 137 138from com.sun.star.script.provider import XScriptProvider, XScript, XScriptContext, ScriptFrameworkErrorException 139from com.sun.star.script.browse import XBrowseNode 140from com.sun.star.script.browse.BrowseNodeTypes import SCRIPT, CONTAINER, ROOT 141from com.sun.star.util import XModifyListener 142 143LANGUAGENAME = "Python" 144GLOBAL_SCRIPTCONTEXT_NAME = "XSCRIPTCONTEXT" 145CALLABLE_CONTAINER_NAME = "g_exportedScripts" 146 147# pythonloader looks for a static g_ImplementationHelper variable 148g_ImplementationHelper = unohelper.ImplementationHelper() 149g_implName = "org.openoffice.pyuno.LanguageScriptProviderFor"+LANGUAGENAME 150 151 152 153BLOCK_SIZE = 65536 154def readTextFromStream( inputStream ): 155 # read the file 156 code = uno.ByteSequence( "" ) 157 while True: 158 read,out = inputStream.readBytes( None , BLOCK_SIZE ) 159 code = code + out 160 if read < BLOCK_SIZE: 161 break 162 return code.value 163 164def toIniName( str ): 165 # TODO: what is the official way to get to know whether i am on the windows platform ? 166 if( hasattr(sys , "dllhandle") ): 167 return str + ".ini" 168 return str + "rc" 169 170class EmptyInputStream( unohelper.Base, XInputStream ): 171 def __init__( self ): 172 pass 173 174 def closeInput(self): 175 pass 176 177 def readBytes( self, seq, n ): 178 return 0, "" 179 180 def readSomeBytes( self, seq, n ): 181 return 0, "" 182 183 def skipBytes( self, n ): 184 pass 185 186 def available( self ): 187 return 0 188 189class BytesInputStream( unohelper.Base, XInputStream ): 190 def __init__( self, bytes ): 191 self.bytes = bytes 192 self.position = 0 193 194 def closeInput(self): 195 pass 196 197 def readBytes( self, seq, n ): 198 size = self.available() 199 if n < size: 200 size = n 201 curr = self.position 202 self.position += size 203 return size, uno.ByteSequence( self.bytes[curr:curr+size] ) 204 205 def readSomeBytes( self, seq, n ): 206 return self.readBytes( seq, n ) 207 208 def skipBytes( self, n ): 209 size = self.available() 210 if n < size: 211 size = n 212 self.position += size 213 214 def available( self ): 215 return len( self.bytes ) - self.position 216 217""" definition: storageURI is the system dependent, absolute file url, where the script is stored on disk 218 scriptURI is the system independent uri 219""" 220class MyUriHelper: 221 222 def __init__( self, ctx, location ): 223 self.s_UriMap = \ 224 { "share" : "vnd.sun.star.expand:${$OOO_BASE_DIR/program/" + toIniName( "bootstrap") + "::BaseInstallation}/share/Scripts/python" , \ 225 "share:uno_packages" : "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE/uno_packages", \ 226 "user" : "vnd.sun.star.expand:${$OOO_BASE_DIR/program/" + toIniName( "bootstrap") + "::UserInstallation}/user/Scripts/python" , \ 227 "user:uno_packages" : "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/uno_packages" } 228 self.m_uriRefFac = ctx.ServiceManager.createInstanceWithContext("com.sun.star.uri.UriReferenceFactory",ctx) 229 if location.startswith( "vnd.sun.star.tdoc" ): 230 self.m_baseUri = location + "/Scripts/python" 231 self.m_scriptUriLocation = "document" 232 else: 233 self.m_baseUri = expandUri( self.s_UriMap[location] ) 234 self.m_scriptUriLocation = location 235 log.debug( "initialized urihelper with baseUri="+self.m_baseUri + ",m_scriptUriLocation="+self.m_scriptUriLocation ) 236 237 def getRootStorageURI( self ): 238 return self.m_baseUri 239 240 def getStorageURI( self, scriptURI ): 241 return self.scriptURI2StorageUri(scriptURI) 242 243 def getScriptURI( self, storageURI ): 244 return self.storageURI2ScriptUri(storageURI) 245 246 def storageURI2ScriptUri( self, storageURI ): 247 if not storageURI.startswith( self.m_baseUri ): 248 message = "pythonscript: storage uri '" + storageURI + "' not in base uri '" + self.m_baseUri + "'" 249 log.debug( message ) 250 raise RuntimeException( message ) 251 252 ret = "vnd.sun.star.script:" + \ 253 storageURI[len(self.m_baseUri)+1:].replace("/","|") + \ 254 "?language=" + LANGUAGENAME + "&location=" + self.m_scriptUriLocation 255 log.debug( "converting storageURI="+storageURI + " to scriptURI=" + ret ) 256 return ret 257 258 def scriptURI2StorageUri( self, scriptURI ): 259 try: 260 myUri = self.m_uriRefFac.parse(scriptURI) 261 ret = self.m_baseUri + "/" + myUri.getName().replace( "|", "/" ) 262 log.debug( "converting scriptURI="+scriptURI + " to storageURI=" + ret ) 263 return ret 264 except UnoException as e: 265 log.error( "error during converting scriptURI="+scriptURI + ": " + e.Message) 266 raise RuntimeException( "pythonscript:scriptURI2StorageUri: " +e.getMessage(), None ) 267 except Exception as e: 268 log.error( "error during converting scriptURI="+scriptURI + ": " + str(e)) 269 raise RuntimeException( "pythonscript:scriptURI2StorageUri: " + str(e), None ) 270 271 272class ModuleEntry: 273 def __init__( self, lastRead, module ): 274 self.lastRead = lastRead 275 self.module = module 276 277def hasChanged( oldDate, newDate ): 278 return newDate.Year > oldDate.Year or \ 279 newDate.Month > oldDate.Month or \ 280 newDate.Day > oldDate.Day or \ 281 newDate.Hours > oldDate.Hours or \ 282 newDate.Minutes > oldDate.Minutes or \ 283 newDate.Seconds > oldDate.Seconds or \ 284 newDate.HundredthSeconds > oldDate.HundredthSeconds 285 286def ensureSourceState( code ): 287 if not code.endswith( "\n" ): 288 code = code + "\n" 289 code = code.replace( "\r", "" ) 290 return code 291 292 293def checkForPythonPathBesideScript( url ): 294 if url.startswith( "file:" ): 295 path = unohelper.fileUrlToSystemPath( url+"/pythonpath.zip" ); 296 log.log( LogLevel.DEBUG, "checking for existence of " + path ) 297 if 1 == os.access( encfile(path), os.F_OK) and not path in sys.path: 298 log.log( LogLevel.DEBUG, "adding " + path + " to sys.path" ) 299 sys.path.append( path ) 300 301 path = unohelper.fileUrlToSystemPath( url+"/pythonpath" ); 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 308class ScriptContext(unohelper.Base): 309 def __init__( self, ctx, doc, inv ): 310 self.ctx = ctx 311 self.doc = doc 312 self.inv = inv 313 314 # XScriptContext 315 def getDocument(self): 316 if self.doc: 317 return self.doc 318 return self.getDesktop().getCurrentComponent() 319 320 def getDesktop(self): 321 return self.ctx.ServiceManager.createInstanceWithContext( 322 "com.sun.star.frame.Desktop", self.ctx ) 323 324 def getComponentContext(self): 325 return self.ctx 326 327 def getInvocationContext(self): 328 return self.inv 329 330#---------------------------------- 331# Global Module Administration 332# does not fit together with script 333# engine lifetime management 334#---------------------------------- 335#g_scriptContext = ScriptContext( uno.getComponentContext(), None ) 336#g_modules = {} 337#def getModuleByUrl( url, sfa ): 338# entry = g_modules.get(url) 339# load = True 340# lastRead = sfa.getDateTimeModified( url ) 341# if entry: 342# if hasChanged( entry.lastRead, lastRead ): 343# log.debug("file " + url + " has changed, reloading") 344# else: 345# load = False 346# 347# if load: 348# log.debug( "opening >" + url + "<" ) 349# 350# code = readTextFromStream( sfa.openFileRead( url ) ) 351 352 # execute the module 353# entry = ModuleEntry( lastRead, imp.new_module("ooo_script_framework") ) 354# entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = g_scriptContext 355# entry.module.__file__ = url 356# exec code in entry.module.__dict__ 357# g_modules[ url ] = entry 358# log.debug( "mapped " + url + " to " + str( entry.module ) ) 359# return entry.module 360 361class ProviderContext: 362 def __init__( self, storageType, sfa, uriHelper, scriptContext ): 363 self.storageType = storageType 364 self.sfa = sfa 365 self.uriHelper = uriHelper 366 self.scriptContext = scriptContext 367 self.modules = {} 368 self.rootUrl = None 369 self.mapPackageName2Path = None 370 371 def getTransientPartFromUrl( self, url ): 372 rest = url.replace( self.rootUrl , "",1 ).replace( "/","",1) 373 return rest[0:rest.find("/")] 374 375 def getPackageNameFromUrl( self, url ): 376 rest = url.replace( self.rootUrl , "",1 ).replace( "/","",1) 377 start = rest.find("/") +1 378 return rest[start:rest.find("/",start)] 379 380 381 def removePackageByUrl( self, url ): 382 items = list(self.mapPackageName2Path.items()) 383 for i in items: 384 if url in i[1].pathes: 385 self.mapPackageName2Path.pop(i[0]) 386 break 387 388 def addPackageByUrl( self, url ): 389 packageName = self.getPackageNameFromUrl( url ) 390 transientPart = self.getTransientPartFromUrl( url ) 391 log.debug( "addPackageByUrl : " + packageName + ", " + transientPart + "("+url+")" + ", rootUrl="+self.rootUrl ) 392 if packageName in self.mapPackageName2Path: 393 package = self.mapPackageName2Path[ packageName ] 394 package.pathes = package.pathes + (url, ) 395 else: 396 package = Package( (url,), transientPart) 397 self.mapPackageName2Path[ packageName ] = package 398 399 def isUrlInPackage( self, url ): 400 values = list(self.mapPackageName2Path.values()) 401 for i in values: 402# print "checking " + url + " in " + str(i.pathes) 403 if url in i.pathes: 404 return True 405# print "false" 406 return False 407 408 def setPackageAttributes( self, mapPackageName2Path, rootUrl ): 409 self.mapPackageName2Path = mapPackageName2Path 410 self.rootUrl = rootUrl 411 412 def getPersistentUrlFromStorageUrl( self, url ): 413 # package name is the second directory 414 ret = url 415 if self.rootUrl: 416 pos = len( self.rootUrl) +1 417 ret = url[0:pos]+url[url.find("/",pos)+1:len(url)] 418 log.debug( "getPersistentUrlFromStorageUrl " + url + " -> "+ ret) 419 return ret 420 421 def getStorageUrlFromPersistentUrl( self, url): 422 ret = url 423 if self.rootUrl: 424 pos = len(self.rootUrl)+1 425 packageName = url[pos:url.find("/",pos+1)] 426 package = self.mapPackageName2Path[ packageName ] 427 ret = url[0:pos]+ package.transientPathElement + "/" + url[pos:len(url)] 428 log.debug( "getStorageUrlFromPersistentUrl " + url + " -> "+ ret) 429 return ret 430 431 def getFuncsByUrl( self, url ): 432 src = readTextFromStream( self.sfa.openFileRead( url ) ) 433 checkForPythonPathBesideScript( url[0:url.rfind('/')] ) 434 src = ensureSourceState( src ) 435 436 allFuncs = [] 437 g_exportedScripts = [] 438 439 a = ast.parse(src, url) 440 441 if isinstance(a, ast.Module): 442 for node in a.body: 443 if isinstance(node, ast.FunctionDef): 444 allFuncs.append(node.name) 445 elif isinstance(node, ast.Assign): 446 is_exported = False 447 for subnode in node.targets: 448 if isinstance(subnode, ast.Name) and \ 449 subnode.id == "g_exportedScripts": 450 is_exported = True 451 break 452 if is_exported: 453 value_node = node.value 454 if isinstance(value_node, ast.List) or \ 455 isinstance(value_node, ast.Tuple): 456 for elt in value_node.elts: 457 if isinstance(elt, ast.Str): 458 g_exportedScripts.append(elt.s) 459 elif isinstance(elt, ast.Name): 460 g_exportedScripts.append(elt.id) 461 elif isinstance(value_node, ast.Str): 462 g_exportedScripts.append(value_node.s) 463 elif isinstance(value_node, ast.Name): 464 g_exportedScripts.append(value_node.id) 465 return g_exportedScripts 466 return allFuncs 467 468 def getModuleByUrl( self, url ): 469 entry = self.modules.get(url) 470 load = True 471 lastRead = self.sfa.getDateTimeModified( url ) 472 if entry: 473 if hasChanged( entry.lastRead, lastRead ): 474 log.debug( "file " + url + " has changed, reloading" ) 475 else: 476 load = False 477 478 if load: 479 log.debug( "opening >" + url + "<" ) 480 481 src = readTextFromStream( self.sfa.openFileRead( url ) ) 482 checkForPythonPathBesideScript( url[0:url.rfind('/')] ) 483 src = ensureSourceState( src ) 484 485 # execute the module 486 entry = ModuleEntry( lastRead, imp.new_module("ooo_script_framework") ) 487 entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.scriptContext 488 489 code = None 490 if url.startswith( "file:" ): 491 code = compile( src, encfile(uno.fileUrlToSystemPath( url ) ), "exec" ) 492 else: 493 code = compile( src, url, "exec" ) 494 exec(code, entry.module.__dict__) 495 entry.module.__file__ = url 496 self.modules[ url ] = entry 497 log.debug( "mapped " + url + " to " + str( entry.module ) ) 498 return entry.module 499 500 # Forgets a stale module so a fresh copy can be loaded in the future. 501 # This is necessary because getModuleByUrl()'s self.sfa.getDateTimeModified() 502 # doesn't always work, eg. for embedded scripts it always returns timestamps 503 # with all zeroes, and even if it worked, the smallest granularity for ZIP file 504 # timestamps is 2 seconds, which isn't good enough. 505 def removeModuleByUrl( self, url ): 506 self.modules.pop( url, None ) 507 508def createEditorDialog( ctx ): 509 smgr = ctx.ServiceManager 510 511 dialogModel = smgr.createInstanceWithContext( 512 "com.sun.star.awt.UnoControlDialogModel", ctx) 513 dialogModel.PositionX = 105 514 dialogModel.PositionY = 117 515 dialogModel.Width = 240 516 dialogModel.Height = 320 517 dialogModel.Closeable = True 518 dialogModel.Moveable = True 519 dialogModel.Title = "Python Macro Editor" 520 521 runButtonModel = dialogModel.createInstance( 522 "com.sun.star.awt.UnoControlButtonModel" ) 523 runButtonModel.PositionX = 57 524 runButtonModel.PositionY = 300 525 runButtonModel.Width = 40 526 runButtonModel.Height = 14 527 runButtonModel.TabIndex = 0 528 runButtonModel.Label = "Run" 529 530 saveButtonModel = dialogModel.createInstance( 531 "com.sun.star.awt.UnoControlButtonModel" ) 532 saveButtonModel.PositionX = 100 533 saveButtonModel.PositionY = 300 534 saveButtonModel.Width = 40 535 saveButtonModel.Height = 14 536 saveButtonModel.TabIndex = 1 537 saveButtonModel.Label = "Save" 538 539 closeButtonModel = dialogModel.createInstance( 540 "com.sun.star.awt.UnoControlButtonModel" ) 541 closeButtonModel.PositionX = 143 542 closeButtonModel.PositionY = 300 543 closeButtonModel.Width = 40 544 closeButtonModel.Height = 14 545 closeButtonModel.TabIndex = 2 546 closeButtonModel.PushButtonType = 2 # CANCEL 547 closeButtonModel.Label = "Close" 548 549 fontDescriptor = FontDescriptor() 550 fontDescriptor.Name = "SomeFixedWidthFont" 551 fontDescriptor.Pitch = FIXED 552 553 textFieldModel = dialogModel.createInstance( 554 "com.sun.star.awt.UnoControlEditModel" ) 555 textFieldModel.PositionX = 6 556 textFieldModel.PositionY = 6 557 textFieldModel.Width = 228 558 textFieldModel.Height = 288 559 textFieldModel.TabIndex = 3 560 textFieldModel.HScroll = True 561 textFieldModel.VScroll = True 562 textFieldModel.MultiLine = True 563 textFieldModel.FontDescriptor = fontDescriptor 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, scriptUri ): 1326 try: 1327 log.debug( "DirBrowseNode getScript " + scriptUri + " invoked") 1328 1329 storageUri = self.provCtx.getStorageUrlFromPersistentUrl( 1330 self.provCtx.uriHelper.getStorageURI(scriptUri) ); 1331 log.debug( "getScript: storageUri = " + storageUri) 1332 fileUri = storageUri[0:storageUri.find( "$" )] 1333 funcName = storageUri[storageUri.find( "$" )+1:len(storageUri)] 1334 1335 mod = self.provCtx.getModuleByUrl( fileUri ) 1336 log.debug( " got mod " + str(mod) ) 1337 1338 func = mod.__dict__[ funcName ] 1339 1340 log.debug( "got func " + str( func ) ) 1341 return PythonScript( func, mod ) 1342 except Exception as e: 1343 text = lastException2String() 1344 log.error( text ) 1345 raise ScriptFrameworkErrorException( text, self, scriptUri, LANGUAGENAME, 0 ) 1346 1347 # XPropertySet 1348 1349 def getPropertyValue( self, name ): 1350 return self.dirBrowseNode.getPropertyValue( name ) 1351 1352 def setPropertyValue( self, name, value ): 1353 return self.dirBrowseNode.setPropertyValue( name, value ) 1354 1355 def getPropertySetInfo( self ): 1356 return self.dirBrowseNode.getPropertySetInfo() 1357 1358 # XInvocation 1359 1360 def getIntrospection( self ): 1361 return self.dirBrowseNode.getIntrospection() 1362 1363 def invoke( self, name, params, outparamindex, outparams ): 1364 return self.dirBrowseNode.invoke( name, params, outparamindex, outparams) 1365 1366 def setValue( self, name, value ): 1367 return self.dirBrowseNode.setValue( name, value ) 1368 1369 def getValue( self, name ): 1370 return self.dirBrowseNode.getValue( name ) 1371 1372 def hasMethod( self, name ): 1373 return self.dirBrowseNode.hasMethod( name ) 1374 1375 def hasProperty( self, name ): 1376 return self.dirBrowseNode.hasProperty( name ) 1377 1378 # XServiceInfo 1379 def getSupportedServices( self ): 1380 return g_ImplementationHelper.getSupportedServices(g_implName) 1381 1382 def supportsService( self, ServiceName ): 1383 return g_ImplementationHelper.supportsService( g_implName, ServiceName ) 1384 1385 def getImplementationName(self): 1386 return g_implName 1387 1388 def getByName( self, name ): 1389 log.debug( "getByName called" + str( name )) 1390 return None 1391 1392 1393 def getElementNames( self ): 1394 log.debug( "getElementNames called") 1395 return () 1396 1397 def hasByName( self, name ): 1398 try: 1399 log.debug( "hasByName called " + str( name )) 1400 uri = expandUri(name) 1401 ret = self.provCtx.isUrlInPackage( uri ) 1402 log.debug( "hasByName " + uri + " " +str( ret ) ) 1403 return ret 1404 except Exception as e: 1405 text = lastException2String() 1406 log.debug( "Error in hasByName:" + text ) 1407 return False 1408 1409 def removeByName( self, name ): 1410 log.debug( "removeByName called" + str( name )) 1411 uri = expandUri( name ) 1412 if self.provCtx.isUrlInPackage( uri ): 1413 self.provCtx.removePackageByUrl( uri ) 1414 else: 1415 log.debug( "removeByName unknown uri " + str( name ) + ", ignoring" ) 1416 raise NoSuchElementException( uri + "is not in package" , self ) 1417 log.debug( "removeByName called" + str( uri ) + " successful" ) 1418 1419 def insertByName( self, name, value ): 1420 log.debug( "insertByName called " + str( name ) + " " + str( value )) 1421 uri = expandUri( name ) 1422 if isPyFileInPath( self.provCtx.sfa, uri ): 1423 self.provCtx.addPackageByUrl( uri ) 1424 else: 1425 # package is no python package ... 1426 log.debug( "insertByName: no python files in " + str( uri ) + ", ignoring" ) 1427 raise IllegalArgumentException( uri + " does not contain .py files", self, 1 ) 1428 log.debug( "insertByName called " + str( uri ) + " successful" ) 1429 1430 def replaceByName( self, name, value ): 1431 log.debug( "replaceByName called " + str( name ) + " " + str( value )) 1432 removeByName( name ) 1433 insertByName( name ) 1434 log.debug( "replaceByName called" + str( uri ) + " successful" ) 1435 1436 def getElementType( self ): 1437 log.debug( "getElementType called" ) 1438 return uno.getTypeByName( "void" ) 1439 1440 def hasElements( self ): 1441 log.debug( "hasElements got called") 1442 return False 1443 1444g_ImplementationHelper.addImplementation( \ 1445 PythonScriptProvider,g_implName, \ 1446 ("com.sun.star.script.provider.LanguageScriptProvider", 1447 "com.sun.star.script.provider.ScriptProviderFor"+ LANGUAGENAME,),) 1448 1449 1450log.debug( "pythonscript finished intializing" ) 1451