1# ************************************************************* 2# 3# Licensed to the Apache Software Foundation (ASF) under one 4# or more contributor license agreements. See the NOTICE file 5# distributed with this work for additional information 6# regarding copyright ownership. The ASF licenses this file 7# to you under the Apache License, Version 2.0 (the 8# "License"); you may not use this file except in compliance 9# with the License. You may obtain a copy of the License at 10# 11# http://www.apache.org/licenses/LICENSE-2.0 12# 13# Unless required by applicable law or agreed to in writing, 14# software distributed under the License is distributed on an 15# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16# KIND, either express or implied. See the License for the 17# specific language governing permissions and limitations 18# under the License. 19# 20# ************************************************************* 21 22# XScript implementation for python 23import uno 24import unohelper 25import sys 26import os 27import imp 28import time 29import ast 30 31try: 32 unicode 33except NameError: 34 unicode = str 35 36class LogLevel: 37 NONE = 0 # production level 38 ERROR = 1 # for script developers 39 DEBUG = 2 # for script framework developers 40 41PYSCRIPT_LOG_ENV = "PYSCRIPT_LOG_LEVEL" 42PYSCRIPT_LOG_STDOUT_ENV = "PYSCRIPT_LOG_STDOUT" 43 44# Configuration ---------------------------------------------------- 45LogLevel.use = LogLevel.NONE 46if os.environ.get(PYSCRIPT_LOG_ENV) == "ERROR": 47 LogLevel.use = LogLevel.ERROR 48elif os.environ.get(PYSCRIPT_LOG_ENV) == "DEBUG": 49 LogLevel.use = LogLevel.DEBUG 50 51# True, writes to stdout (difficult on windows) 52# False, writes to user/Scripts/python/log.txt 53LOG_STDOUT = os.environ.get(PYSCRIPT_LOG_STDOUT_ENV, "1") != "0" 54 55#------------------------------------------------------------------- 56 57def encfile(uni): 58 if sys.version_info[0] > 2: 59 return uni 60 else: 61 return uni.encode( sys.getfilesystemencoding()) 62 63def lastException2String(): 64 (excType,excInstance,excTraceback) = sys.exc_info() 65 ret = str(excType) + ": "+str(excInstance) + "\n" + \ 66 uno._uno_extract_printable_stacktrace( excTraceback ) 67 return ret 68 69def logLevel2String( level ): 70 ret = " NONE" 71 if level == LogLevel.ERROR: 72 ret = "ERROR" 73 elif level >= LogLevel.DEBUG: 74 ret = "DEBUG" 75 return ret 76 77def getLogTarget(): 78 ret = sys.stdout 79 if not LOG_STDOUT: 80 try: 81 pathSubst = uno.getComponentContext().ServiceManager.createInstance( 82 "com.sun.star.util.PathSubstitution" ) 83 userInstallation = pathSubst.getSubstituteVariableValue( "user" ) 84 if len( userInstallation ) > 0: 85 systemPath = uno.fileUrlToSystemPath( userInstallation + "/Scripts/python/log.txt" ) 86 ret = open( systemPath , "a" ) 87 except Exception as e: 88 print("Exception during creation of pythonscript logfile: "+ lastException2String() + "\n, delagating log to stdout\n") 89 return ret 90 91class Logger(LogLevel): 92 def __init__(self , target ): 93 self.target = target 94 95 def isDebugLevel( self ): 96 return self.use >= self.DEBUG 97 98 def debug( self, msg ): 99 if self.isDebugLevel(): 100 self.log( self.DEBUG, msg ) 101 102 def isErrorLevel( self ): 103 return self.use >= self.ERROR 104 105 def error( self, msg ): 106 if self.isErrorLevel(): 107 self.log( self.ERROR, msg ) 108 109 def log( self, level, msg ): 110 if self.use >= level: 111 try: 112 self.target.write( 113 time.asctime() + 114 " [" + 115 logLevel2String( level ) + 116 "] " + 117 encfile(msg) + 118 "\n" ) 119 self.target.flush() 120 except Exception as e: 121 print("Error during writing to stdout: " +lastException2String() + "\n") 122 123log = Logger( getLogTarget() ) 124 125log.debug( "pythonscript loading" ) 126 127#from com.sun.star.lang import typeOfXServiceInfo, typeOfXTypeProvider 128from com.sun.star.uno import RuntimeException 129from com.sun.star.lang import XServiceInfo 130from com.sun.star.io import IOException, XInputStream 131from com.sun.star.ucb import CommandAbortedException, XCommandEnvironment, XProgressHandler, Command 132from com.sun.star.task import XInteractionHandler 133from com.sun.star.beans import XPropertySet, Property 134from com.sun.star.container import XNameContainer 135from com.sun.star.xml.sax import XDocumentHandler, InputSource 136from com.sun.star.uno import Exception as UnoException 137from com.sun.star.script import XInvocation 138from com.sun.star.awt import XActionListener 139 140from com.sun.star.script.provider import XScriptProvider, XScript, XScriptContext, ScriptFrameworkErrorException 141from com.sun.star.script.browse import XBrowseNode 142from com.sun.star.script.browse.BrowseNodeTypes import SCRIPT, CONTAINER, ROOT 143from com.sun.star.util import XModifyListener 144 145LANGUAGENAME = "Python" 146GLOBAL_SCRIPTCONTEXT_NAME = "XSCRIPTCONTEXT" 147CALLABLE_CONTAINER_NAME = "g_exportedScripts" 148 149# pythonloader looks for a static g_ImplementationHelper variable 150g_ImplementationHelper = unohelper.ImplementationHelper() 151g_implName = "org.openoffice.pyuno.LanguageScriptProviderFor"+LANGUAGENAME 152 153 154 155BLOCK_SIZE = 65536 156def readTextFromStream( inputStream ): 157 # read the file 158 code = uno.ByteSequence( b"" ) 159 while True: 160 read,out = inputStream.readBytes( None , BLOCK_SIZE ) 161 code = code + out 162 if read < BLOCK_SIZE: 163 break 164 if sys.version_info[0] > 2: 165 return str( code.value, 'utf-8' ) 166 else: 167 return code.value 168 169def toIniName( str ): 170 # TODO: what is the official way to get to know whether i am on the windows platform ? 171 if( hasattr(sys , "dllhandle") ): 172 return str + ".ini" 173 return str + "rc" 174 175class EmptyInputStream( unohelper.Base, XInputStream ): 176 def __init__( self ): 177 pass 178 179 def closeInput(self): 180 pass 181 182 def readBytes( self, seq, n ): 183 return 0, "" 184 185 def readSomeBytes( self, seq, n ): 186 return 0, "" 187 188 def skipBytes( self, n ): 189 pass 190 191 def available( self ): 192 return 0 193 194class BytesInputStream( unohelper.Base, XInputStream ): 195 def __init__( self, bytes ): 196 self.bytes = bytes 197 self.position = 0 198 199 def closeInput(self): 200 pass 201 202 def readBytes( self, seq, n ): 203 size = self.available() 204 if n < size: 205 size = n 206 curr = self.position 207 self.position += size 208 return size, uno.ByteSequence( self.bytes[curr:curr+size] ) 209 210 def readSomeBytes( self, seq, n ): 211 return self.readBytes( seq, n ) 212 213 def skipBytes( self, n ): 214 size = self.available() 215 if n < size: 216 size = n 217 self.position += size 218 219 def available( self ): 220 return len( self.bytes ) - self.position 221 222""" definition: storageURI is the system dependent, absolute file url, where the script is stored on disk 223 scriptURI is the system independent uri 224""" 225class MyUriHelper: 226 227 def __init__( self, ctx, location ): 228 self.s_UriMap = \ 229 { "share" : "vnd.sun.star.expand:${$OOO_BASE_DIR/program/" + toIniName( "bootstrap") + "::BaseInstallation}/share/Scripts/python" , \ 230 "share:uno_packages" : "vnd.sun.star.expand:$UNO_SHARED_PACKAGES_CACHE/uno_packages", \ 231 "user" : "vnd.sun.star.expand:${$OOO_BASE_DIR/program/" + toIniName( "bootstrap") + "::UserInstallation}/user/Scripts/python" , \ 232 "user:uno_packages" : "vnd.sun.star.expand:$UNO_USER_PACKAGES_CACHE/uno_packages" } 233 self.m_uriRefFac = ctx.ServiceManager.createInstanceWithContext("com.sun.star.uri.UriReferenceFactory",ctx) 234 if location.startswith( "vnd.sun.star.tdoc" ): 235 self.m_baseUri = location + "/Scripts/python" 236 self.m_scriptUriLocation = "document" 237 else: 238 self.m_baseUri = expandUri( self.s_UriMap[location] ) 239 self.m_scriptUriLocation = location 240 log.debug( "initialized urihelper with baseUri="+self.m_baseUri + ",m_scriptUriLocation="+self.m_scriptUriLocation ) 241 242 def getRootStorageURI( self ): 243 return self.m_baseUri 244 245 def getStorageURI( self, scriptURI ): 246 return self.scriptURI2StorageUri(scriptURI) 247 248 def getScriptURI( self, storageURI ): 249 return self.storageURI2ScriptUri(storageURI) 250 251 def storageURI2ScriptUri( self, storageURI ): 252 if not storageURI.startswith( self.m_baseUri ): 253 message = "pythonscript: storage uri '" + storageURI + "' not in base uri '" + self.m_baseUri + "'" 254 log.debug( message ) 255 raise RuntimeException( message ) 256 257 ret = "vnd.sun.star.script:" + \ 258 storageURI[len(self.m_baseUri)+1:].replace("/","|") + \ 259 "?language=" + LANGUAGENAME + "&location=" + self.m_scriptUriLocation 260 log.debug( "converting storageURI="+storageURI + " to scriptURI=" + ret ) 261 return ret 262 263 def scriptURI2StorageUri( self, scriptURI ): 264 try: 265 myUri = self.m_uriRefFac.parse(scriptURI) 266 ret = self.m_baseUri + "/" + myUri.getName().replace( "|", "/" ) 267 log.debug( "converting scriptURI="+scriptURI + " to storageURI=" + ret ) 268 return ret 269 except UnoException as e: 270 log.error( "error during converting scriptURI="+scriptURI + ": " + e.Message) 271 raise RuntimeException( "pythonscript:scriptURI2StorageUri: " +e.getMessage(), None ) 272 except Exception as e: 273 log.error( "error during converting scriptURI="+scriptURI + ": " + str(e)) 274 raise RuntimeException( "pythonscript:scriptURI2StorageUri: " + str(e), None ) 275 276 277class ModuleEntry: 278 def __init__( self, lastRead, module ): 279 self.lastRead = lastRead 280 self.module = module 281 282def hasChanged( oldDate, newDate ): 283 return newDate.Year > oldDate.Year or \ 284 newDate.Month > oldDate.Month or \ 285 newDate.Day > oldDate.Day or \ 286 newDate.Hours > oldDate.Hours or \ 287 newDate.Minutes > oldDate.Minutes or \ 288 newDate.Seconds > oldDate.Seconds or \ 289 newDate.HundredthSeconds > oldDate.HundredthSeconds 290 291def ensureSourceState( code ): 292 if not code.endswith( "\n" ): 293 code = code + "\n" 294 code = code.replace( "\r", "" ) 295 return code 296 297 298def checkForPythonPathBesideScript( url ): 299 if url.startswith( "file:" ): 300 path = unohelper.fileUrlToSystemPath( url+"/pythonpath.zip" ); 301 log.log( LogLevel.DEBUG, "checking for existence of " + path ) 302 if 1 == os.access( encfile(path), os.F_OK) and not path in sys.path: 303 log.log( LogLevel.DEBUG, "adding " + path + " to sys.path" ) 304 sys.path.append( path ) 305 306 path = unohelper.fileUrlToSystemPath( url+"/pythonpath" ); 307 log.log( LogLevel.DEBUG, "checking for existence of " + path ) 308 if 1 == os.access( encfile(path), os.F_OK) and not path in sys.path: 309 log.log( LogLevel.DEBUG, "adding " + path + " to sys.path" ) 310 sys.path.append( path ) 311 312 313class ScriptContext(unohelper.Base): 314 def __init__( self, ctx, doc, inv ): 315 self.ctx = ctx 316 self.doc = doc 317 self.inv = inv 318 319 # XScriptContext 320 def getDocument(self): 321 if self.doc: 322 return self.doc 323 return self.getDesktop().getCurrentComponent() 324 325 def getDesktop(self): 326 return self.ctx.ServiceManager.createInstanceWithContext( 327 "com.sun.star.frame.Desktop", self.ctx ) 328 329 def getComponentContext(self): 330 return self.ctx 331 332 def getInvocationContext(self): 333 return self.inv 334 335#---------------------------------- 336# Global Module Administration 337# does not fit together with script 338# engine lifetime management 339#---------------------------------- 340#g_scriptContext = ScriptContext( uno.getComponentContext(), None ) 341#g_modules = {} 342#def getModuleByUrl( url, sfa ): 343# entry = g_modules.get(url) 344# load = True 345# lastRead = sfa.getDateTimeModified( url ) 346# if entry: 347# if hasChanged( entry.lastRead, lastRead ): 348# log.debug("file " + url + " has changed, reloading") 349# else: 350# load = False 351# 352# if load: 353# log.debug( "opening >" + url + "<" ) 354# 355# code = readTextFromStream( sfa.openFileRead( url ) ) 356 357 # execute the module 358# entry = ModuleEntry( lastRead, imp.new_module("ooo_script_framework") ) 359# entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = g_scriptContext 360# entry.module.__file__ = url 361# exec code in entry.module.__dict__ 362# g_modules[ url ] = entry 363# log.debug( "mapped " + url + " to " + str( entry.module ) ) 364# return entry.module 365 366class ProviderContext: 367 def __init__( self, storageType, sfa, uriHelper, scriptContext ): 368 self.storageType = storageType 369 self.sfa = sfa 370 self.uriHelper = uriHelper 371 self.scriptContext = scriptContext 372 self.modules = {} 373 self.rootUrl = None 374 self.mapPackageName2Path = None 375 376 def getTransientPartFromUrl( self, url ): 377 rest = url.replace( self.rootUrl , "",1 ).replace( "/","",1) 378 return rest[0:rest.find("/")] 379 380 def getPackageNameFromUrl( self, url ): 381 rest = url.replace( self.rootUrl , "",1 ).replace( "/","",1) 382 start = rest.find("/") +1 383 return rest[start:rest.find("/",start)] 384 385 386 def removePackageByUrl( self, url ): 387 items = list(self.mapPackageName2Path.items()) 388 for i in items: 389 if url in i[1].pathes: 390 self.mapPackageName2Path.pop(i[0]) 391 break 392 393 def addPackageByUrl( self, url ): 394 packageName = self.getPackageNameFromUrl( url ) 395 transientPart = self.getTransientPartFromUrl( url ) 396 log.debug( "addPackageByUrl : " + packageName + ", " + transientPart + "("+url+")" + ", rootUrl="+self.rootUrl ) 397 if packageName in self.mapPackageName2Path: 398 package = self.mapPackageName2Path[ packageName ] 399 package.pathes = package.pathes + (url, ) 400 else: 401 package = Package( (url,), transientPart) 402 self.mapPackageName2Path[ packageName ] = package 403 404 def isUrlInPackage( self, url ): 405 values = list(self.mapPackageName2Path.values()) 406 for i in values: 407# print "checking " + url + " in " + str(i.pathes) 408 if url in i.pathes: 409 return True 410# print "false" 411 return False 412 413 def setPackageAttributes( self, mapPackageName2Path, rootUrl ): 414 self.mapPackageName2Path = mapPackageName2Path 415 self.rootUrl = rootUrl 416 417 def getPersistentUrlFromStorageUrl( self, url ): 418 # package name is the second directory 419 ret = url 420 if self.rootUrl: 421 pos = len( self.rootUrl) +1 422 ret = url[0:pos]+url[url.find("/",pos)+1:len(url)] 423 log.debug( "getPersistentUrlFromStorageUrl " + url + " -> "+ ret) 424 return ret 425 426 def getStorageUrlFromPersistentUrl( self, url): 427 ret = url 428 if self.rootUrl: 429 pos = len(self.rootUrl)+1 430 packageName = url[pos:url.find("/",pos+1)] 431 package = self.mapPackageName2Path[ packageName ] 432 ret = url[0:pos]+ package.transientPathElement + "/" + url[pos:len(url)] 433 log.debug( "getStorageUrlFromPersistentUrl " + url + " -> "+ ret) 434 return ret 435 436 def getFuncsByUrl( self, url ): 437 src = readTextFromStream( self.sfa.openFileRead( url ) ) 438 checkForPythonPathBesideScript( url[0:url.rfind('/')] ) 439 src = ensureSourceState( src ) 440 441 allFuncs = [] 442 g_exportedScripts = [] 443 444 a = ast.parse(src, url) 445 446 if isinstance(a, ast.Module): 447 for node in a.body: 448 if isinstance(node, ast.FunctionDef): 449 allFuncs.append(node.name) 450 elif isinstance(node, ast.Assign): 451 is_exported = False 452 for subnode in node.targets: 453 if isinstance(subnode, ast.Name) and \ 454 subnode.id == "g_exportedScripts": 455 is_exported = True 456 break 457 if is_exported: 458 value_node = node.value 459 if isinstance(value_node, ast.List) or \ 460 isinstance(value_node, ast.Tuple): 461 for elt in value_node.elts: 462 if isinstance(elt, ast.Str): 463 g_exportedScripts.append(elt.s) 464 elif isinstance(elt, ast.Name): 465 g_exportedScripts.append(elt.id) 466 elif isinstance(value_node, ast.Str): 467 g_exportedScripts.append(value_node.s) 468 elif isinstance(value_node, ast.Name): 469 g_exportedScripts.append(value_node.id) 470 return g_exportedScripts 471 return allFuncs 472 473 def getModuleByUrl( self, url ): 474 entry = self.modules.get(url) 475 load = True 476 lastRead = self.sfa.getDateTimeModified( url ) 477 if entry: 478 if hasChanged( entry.lastRead, lastRead ): 479 log.debug( "file " + url + " has changed, reloading" ) 480 else: 481 load = False 482 483 if load: 484 log.debug( "opening >" + url + "<" ) 485 486 src = readTextFromStream( self.sfa.openFileRead( url ) ) 487 checkForPythonPathBesideScript( url[0:url.rfind('/')] ) 488 src = ensureSourceState( src ) 489 490 # execute the module 491 entry = ModuleEntry( lastRead, imp.new_module("ooo_script_framework") ) 492 entry.module.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.scriptContext 493 494 code = None 495 if url.startswith( "file:" ): 496 code = compile( src, encfile(uno.fileUrlToSystemPath( url ) ), "exec" ) 497 else: 498 code = compile( src, url, "exec" ) 499 exec(code, entry.module.__dict__) 500 entry.module.__file__ = url 501 self.modules[ url ] = entry 502 log.debug( "mapped " + url + " to " + str( entry.module ) ) 503 return entry.module 504 505 # Forgets a stale module so a fresh copy can be loaded in the future. 506 # This is necessary because getModuleByUrl()'s self.sfa.getDateTimeModified() 507 # doesn't always work, eg. for embedded scripts it always returns timestamps 508 # with all zeroes, and even if it worked, the smallest granularity for ZIP file 509 # timestamps is 2 seconds, which isn't good enough. 510 def removeModuleByUrl( self, url ): 511 del self.modules[ url ] 512 513def createEditorDialog( ctx ): 514 smgr = ctx.ServiceManager 515 516 dialogModel = smgr.createInstanceWithContext( 517 "com.sun.star.awt.UnoControlDialogModel", ctx) 518 dialogModel.PositionX = 105 519 dialogModel.PositionY = 117 520 dialogModel.Width = 240 521 dialogModel.Height = 320 522 dialogModel.Closeable = True 523 dialogModel.Moveable = True 524 dialogModel.Title = "Python Macro Editor" 525 526 runButtonModel = dialogModel.createInstance( 527 "com.sun.star.awt.UnoControlButtonModel" ) 528 runButtonModel.PositionX = 57 529 runButtonModel.PositionY = 300 530 runButtonModel.Width = 40 531 runButtonModel.Height = 14 532 runButtonModel.TabIndex = 0 533 runButtonModel.Label = "Run" 534 535 saveButtonModel = dialogModel.createInstance( 536 "com.sun.star.awt.UnoControlButtonModel" ) 537 saveButtonModel.PositionX = 100 538 saveButtonModel.PositionY = 300 539 saveButtonModel.Width = 40 540 saveButtonModel.Height = 14 541 saveButtonModel.TabIndex = 1 542 saveButtonModel.Label = "Save" 543 544 closeButtonModel = dialogModel.createInstance( 545 "com.sun.star.awt.UnoControlButtonModel" ) 546 closeButtonModel.PositionX = 143 547 closeButtonModel.PositionY = 300 548 closeButtonModel.Width = 40 549 closeButtonModel.Height = 14 550 closeButtonModel.TabIndex = 2 551 closeButtonModel.PushButtonType = 2 # CANCEL 552 closeButtonModel.Label = "Close" 553 554 textFieldModel = dialogModel.createInstance( 555 "com.sun.star.awt.UnoControlEditModel" ) 556 textFieldModel.PositionX = 6 557 textFieldModel.PositionY = 6 558 textFieldModel.Width = 228 559 textFieldModel.Height = 288 560 textFieldModel.TabIndex = 3 561 textFieldModel.HScroll = True 562 textFieldModel.VScroll = True 563 textFieldModel.MultiLine = True 564 565 dialogModel.insertByName( "RunButton", runButtonModel ) 566 dialogModel.insertByName( "SaveButton", saveButtonModel ) 567 dialogModel.insertByName( "CloseButton", closeButtonModel ) 568 dialogModel.insertByName( "EditorTextField", textFieldModel ) 569 570 # create the dialog control and set the model 571 controlContainer = smgr.createInstanceWithContext( 572 "com.sun.star.awt.UnoControlDialog", ctx); 573 controlContainer.setModel(dialogModel); 574 575 # create a peer 576 toolkit = smgr.createInstanceWithContext( 577 "com.sun.star.awt.ExtToolkit", ctx); 578 579 controlContainer.setVisible(False); 580 controlContainer.createPeer(toolkit, None); 581 582 return controlContainer 583 584 585#-------------------------------------------------- 586def isScript( candidate ): 587 ret = False 588 if isinstance( candidate, type(isScript) ): 589 ret = True 590 return ret 591 592#------------------------------------------------------- 593class ScriptBrowseNode( unohelper.Base, XBrowseNode, XPropertySet, XInvocation, XActionListener ): 594 def __init__( self, provCtx, parent, fileName, funcName ): 595 self.parent = parent 596 self.fileName = fileName 597 self.funcName = funcName 598 self.provCtx = provCtx 599 600 def uri( self ): 601 return self.parent.uri() 602 603 def getName( self ): 604 return self.funcName 605 606 def getChildNodes(self): 607 return () 608 609 def hasChildNodes(self): 610 return False 611 612 def getType( self): 613 return SCRIPT 614 615 def getPropertyValue( self, name ): 616 ret = None 617 try: 618 if name == "URI": 619 ret = self.provCtx.uriHelper.getScriptURI( 620 self.provCtx.getPersistentUrlFromStorageUrl( self.uri() + "$" + self.funcName ) ) 621 elif name == "Editable": 622 ret = not self.provCtx.sfa.isReadOnly( self.uri() ) 623 624 log.debug( "ScriptBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) ) 625 except Exception as e: 626 log.error( "ScriptBrowseNode.getPropertyValue error " + lastException2String()) 627 raise 628 629 return ret 630 def setPropertyValue( self, name, value ): 631 log.debug( "ScriptBrowseNode.setPropertyValue called " + name + "=" +str(value ) ) 632 def getPropertySetInfo( self ): 633 log.debug( "ScriptBrowseNode.getPropertySetInfo called " ) 634 return None 635 636 def getIntrospection( self ): 637 return None 638 639 def invoke( self, name, params, outparamindex, outparams ): 640 if name == "Editable": 641 ctx = self.provCtx.scriptContext.getComponentContext() 642 643 self.editor = createEditorDialog( ctx ) 644 645 code = readTextFromStream(self.provCtx.sfa.openFileRead(self.uri())) 646 code = ensureSourceState( code ) 647 self.editor.getControl("EditorTextField").setText(code) 648 649 self.editor.getControl("RunButton").setActionCommand("Run") 650 self.editor.getControl("RunButton").addActionListener(self) 651 self.editor.getControl("SaveButton").setActionCommand("Save") 652 self.editor.getControl("SaveButton").addActionListener(self) 653 654 self.editor.execute() 655 656 return None, (), () 657 658 def actionPerformed( self, event ): 659 try: 660 if event.ActionCommand == "Run": 661 code = self.editor.getControl("EditorTextField").getText() 662 code = ensureSourceState( code ) 663 mod = imp.new_module("ooo_script_framework") 664 mod.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.provCtx.scriptContext 665 exec(code, mod.__dict__) 666 values = mod.__dict__.get( CALLABLE_CONTAINER_NAME , None ) 667 if not values: 668 values = list(mod.__dict__.values()) 669 670 for i in values: 671 if isScript( i ): 672 i() 673 break 674 675 elif event.ActionCommand == "Save": 676 toWrite = uno.ByteSequence( 677 self.editor.getControl("EditorTextField").getText().encode("utf-8")) 678 copyUrl = self.uri() + ".orig" 679 self.provCtx.sfa.move( self.uri(), copyUrl ) 680 log.debug( "Saving Python macro to URI " + self.uri() ) 681 self.provCtx.sfa.writeFile( self.uri(), BytesInputStream( toWrite.value ) ) 682 self.provCtx.removeModuleByUrl( self.uri() ) 683 self.provCtx.sfa.kill( copyUrl ) 684 except Exception as e: 685 # TODO: add an error box here ! 686 log.error( lastException2String() ) 687 688 689 def setValue( self, name, value ): 690 return None 691 692 def getValue( self, name ): 693 return None 694 695 def hasMethod( self, name ): 696 return False 697 698 def hasProperty( self, name ): 699 return False 700 701 702#------------------------------------------------------- 703class FileBrowseNode( unohelper.Base, XBrowseNode, XPropertySet, XInvocation, XActionListener ): 704 def __init__( self, provCtx, parent, name ): 705 self.provCtx = provCtx 706 self.parent = parent 707 self.name = name 708 self.funcnames = None 709 710 def uri( self ): 711 return self.parent.rootUrl + "/" + self.name + ".py" 712 713 def getName( self ): 714 return self.name 715 716 def getChildNodes(self): 717 ret = () 718 try: 719 self.funcnames = self.provCtx.getFuncsByUrl( self.uri() ) 720 721 scriptNodeList = [] 722 for i in self.funcnames: 723 scriptNodeList.append( 724 ScriptBrowseNode( 725 self.provCtx, self, self.name, i )) 726 ret = tuple( scriptNodeList ) 727 except Exception as e: 728 text = lastException2String() 729 log.error( "FileBrowseNode.getChildNodes error while evaluating " + self.uri() + ":" + text ) 730 raise 731 return ret 732 733 def hasChildNodes(self): 734 try: 735 return len(self.getChildNodes()) > 0 736 except Exception as e: 737 return False 738 739 def getType( self): 740 return CONTAINER 741 742 # XPropertySet 743 744 def getPropertyValue( self, name ): 745 ret = None 746 try: 747 if name == "Editable": 748 ret = not self.provCtx.sfa.isReadOnly( self.uri() ) 749 elif name == "Deletable": 750 ret = not self.provCtx.sfa.isReadOnly( self.uri() ) 751 elif name == "Renamable": 752 ret = not self.provCtx.sfa.isReadOnly( self.uri() ) 753 754 log.debug( "FileBrowseNode.getPropertyValue called for " + name + ", returning " + str(ret) ) 755 except Exception as e: 756 log.error( "FileBrowseNode.getPropertyValue error " + lastException2String()) 757 raise 758 759 return ret 760 761 def setPropertyValue( self, name, value ): 762 log.debug( "FileBrowseNode.setPropertyValue called " + name + "=" +str(value ) ) 763 764 def getPropertySetInfo( self ): 765 log.debug( "FileBrowseNode.getPropertySetInfo called " ) 766 return None 767 768 # XInvocation 769 770 def getIntrospection( self ): 771 log.debug( "FileBrowseNode.getIntrospection() called" ) 772 return None 773 774 def invoke( self, name, params, outparamindex, outparams ): 775 log.debug("FileBrowseNode.invoke called for " + name + "," + str(params) + "," + str(outparamindex) + "," + str(outparams)) 776 try: 777 if name == "Editable": 778 ctx = self.provCtx.scriptContext.getComponentContext() 779 780 self.editor = createEditorDialog( ctx ) 781 782 code = readTextFromStream(self.provCtx.sfa.openFileRead(self.uri())) 783 code = ensureSourceState( code ) 784 self.editor.getControl("EditorTextField").setText(code) 785 786 self.editor.getControl("RunButton").setActionCommand("Run") 787 self.editor.getControl("RunButton").addActionListener(self) 788 self.editor.getControl("SaveButton").setActionCommand("Save") 789 self.editor.getControl("SaveButton").addActionListener(self) 790 791 self.editor.execute() 792 elif name == "Deletable": 793 self.provCtx.sfa.kill( self.uri() ) 794 return True, (), () 795 elif name == "Renamable": 796 if params is None or not params: 797 raise IllegalArgumentException( "invoke with Creatable needs the name in params" ) 798 newUri = self.parent.rootUrl + "/" + params[0] + ".py" 799 self.provCtx.sfa.move( self.uri(), newUri ) 800 self.name = params[0] 801 return self, (), () 802 except Exception as e: 803 log.error( "FileBrowseNode.invoke error " + lastException2String() ) 804 raise 805 return None, (), () 806 807 def setValue( self, name, value ): 808 return None 809 810 def getValue( self, name ): 811 log.debug( "FileBrowseNode.getValue() called" ) 812 return None 813 814 def hasMethod( self, name ): 815 return False 816 817 def hasProperty( self, name ): 818 return False 819 820 # XActionListener 821 822 def actionPerformed( self, event ): 823 try: 824 if event.ActionCommand == "Run": 825 code = self.editor.getControl("EditorTextField").getText() 826 code = ensureSourceState( code ) 827 mod = imp.new_module("ooo_script_framework") 828 mod.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.provCtx.scriptContext 829 exec(code, mod.__dict__) 830 values = mod.__dict__.get( CALLABLE_CONTAINER_NAME , None ) 831 if not values: 832 values = list(mod.__dict__.values()) 833 834 for i in values: 835 if isScript( i ): 836 i() 837 break 838 839 elif event.ActionCommand == "Save": 840 toWrite = uno.ByteSequence( 841 self.editor.getControl("EditorTextField").getText().encode("utf-8")) 842 copyUrl = self.uri() + ".orig" 843 self.provCtx.sfa.move( self.uri(), copyUrl ) 844 log.debug( "Saving Python macro to URI " + self.uri() ) 845 self.provCtx.sfa.writeFile( self.uri(), BytesInputStream( toWrite.value ) ) 846 self.provCtx.removeModuleByUrl( self.uri() ) 847 self.provCtx.sfa.kill( copyUrl ) 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, uri ): 1332 log.debug( "DirBrowseNode getScript " + uri + " invoked" ) 1333 1334 raise IllegalArgumentException( "DirBrowseNode couldn't instantiate script " + uri , self , 0 ) 1335 1336 def getScript( self, scriptUri ): 1337 try: 1338 log.debug( "getScript " + scriptUri + " invoked") 1339 1340 storageUri = self.provCtx.getStorageUrlFromPersistentUrl( 1341 self.provCtx.uriHelper.getStorageURI(scriptUri) ); 1342 log.debug( "getScript: storageUri = " + storageUri) 1343 fileUri = storageUri[0:storageUri.find( "$" )] 1344 funcName = storageUri[storageUri.find( "$" )+1:len(storageUri)] 1345 1346 mod = self.provCtx.getModuleByUrl( fileUri ) 1347 log.debug( " got mod " + str(mod) ) 1348 1349 func = mod.__dict__[ funcName ] 1350 1351 log.debug( "got func " + str( func ) ) 1352 return PythonScript( func, mod ) 1353 except Exception as e: 1354 text = lastException2String() 1355 log.error( text ) 1356 raise ScriptFrameworkErrorException( text, self, scriptUri, LANGUAGENAME, 0 ) 1357 1358 # XPropertySet 1359 1360 def getPropertyValue( self, name ): 1361 return self.dirBrowseNode.getPropertyValue( name ) 1362 1363 def setPropertyValue( self, name, value ): 1364 return self.dirBrowseNode.setPropertyValue( name, value ) 1365 1366 def getPropertySetInfo( self ): 1367 return self.dirBrowseNode.getPropertySetInfo() 1368 1369 # XInvocation 1370 1371 def getIntrospection( self ): 1372 return self.dirBrowseNode.getIntrospection() 1373 1374 def invoke( self, name, params, outparamindex, outparams ): 1375 return self.dirBrowseNode.invoke( name, params, outparamindex, outparams) 1376 1377 def setValue( self, name, value ): 1378 return self.dirBrowseNode.setValue( name, value ) 1379 1380 def getValue( self, name ): 1381 return self.dirBrowseNode.getValue( name ) 1382 1383 def hasMethod( self, name ): 1384 return self.dirBrowseNode.hasMethod( name ) 1385 1386 def hasProperty( self, name ): 1387 return self.dirBrowseNode.hasProperty( name ) 1388 1389 # XServiceInfo 1390 def getSupportedServices( self ): 1391 return g_ImplementationHelper.getSupportedServices(g_implName) 1392 1393 def supportsService( self, ServiceName ): 1394 return g_ImplementationHelper.supportsService( g_implName, ServiceName ) 1395 1396 def getImplementationName(self): 1397 return g_implName 1398 1399 def getByName( self, name ): 1400 log.debug( "getByName called" + str( name )) 1401 return None 1402 1403 1404 def getElementNames( self ): 1405 log.debug( "getElementNames called") 1406 return () 1407 1408 def hasByName( self, name ): 1409 try: 1410 log.debug( "hasByName called " + str( name )) 1411 uri = expandUri(name) 1412 ret = self.provCtx.isUrlInPackage( uri ) 1413 log.debug( "hasByName " + uri + " " +str( ret ) ) 1414 return ret 1415 except Exception as e: 1416 text = lastException2String() 1417 log.debug( "Error in hasByName:" + text ) 1418 return False 1419 1420 def removeByName( self, name ): 1421 log.debug( "removeByName called" + str( name )) 1422 uri = expandUri( name ) 1423 if self.provCtx.isUrlInPackage( uri ): 1424 self.provCtx.removePackageByUrl( uri ) 1425 else: 1426 log.debug( "removeByName unknown uri " + str( name ) + ", ignoring" ) 1427 raise NoSuchElementException( uri + "is not in package" , self ) 1428 log.debug( "removeByName called" + str( uri ) + " successful" ) 1429 1430 def insertByName( self, name, value ): 1431 log.debug( "insertByName called " + str( name ) + " " + str( value )) 1432 uri = expandUri( name ) 1433 if isPyFileInPath( self.provCtx.sfa, uri ): 1434 self.provCtx.addPackageByUrl( uri ) 1435 else: 1436 # package is no python package ... 1437 log.debug( "insertByName: no python files in " + str( uri ) + ", ignoring" ) 1438 raise IllegalArgumentException( uri + " does not contain .py files", self, 1 ) 1439 log.debug( "insertByName called " + str( uri ) + " successful" ) 1440 1441 def replaceByName( self, name, value ): 1442 log.debug( "replaceByName called " + str( name ) + " " + str( value )) 1443 removeByName( name ) 1444 insertByName( name ) 1445 log.debug( "replaceByName called" + str( uri ) + " successful" ) 1446 1447 def getElementType( self ): 1448 log.debug( "getElementType called" ) 1449 return uno.getTypeByName( "void" ) 1450 1451 def hasElements( self ): 1452 log.debug( "hasElements got called") 1453 return False 1454 1455g_ImplementationHelper.addImplementation( \ 1456 PythonScriptProvider,g_implName, \ 1457 ("com.sun.star.script.provider.LanguageScriptProvider", 1458 "com.sun.star.script.provider.ScriptProviderFor"+ LANGUAGENAME,),) 1459 1460 1461log.debug( "pythonscript finished initializing" ) 1462