1# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*- 2# 3# This file is part of the LibreOffice project. 4# 5# This Source Code Form is subject to the terms of the Mozilla Public 6# License, v. 2.0. If a copy of the MPL was not distributed with this 7# file, You can obtain one at http://mozilla.org/MPL/2.0/. 8# 9# This file incorporates work covered by the following license notice: 10# 11# Licensed to the Apache Software Foundation (ASF) under one or more 12# contributor license agreements. See the NOTICE file distributed 13# with this work for additional information regarding copyright 14# ownership. The ASF licenses this file to you under the Apache 15# License, Version 2.0 (the "License"); you may not use this file 16# except in compliance with the License. You may obtain a copy of 17# the License at http://www.apache.org/licenses/LICENSE-2.0 . 18# 19import uno 20import pyuno 21import os 22import sys 23 24from com.sun.star.lang import XTypeProvider, XSingleComponentFactory, XServiceInfo 25from com.sun.star.uno import RuntimeException, XCurrentContext 26from com.sun.star.beans.MethodConcept import ALL as METHOD_CONCEPT_ALL 27from com.sun.star.beans.PropertyConcept import ALL as PROPERTY_CONCEPT_ALL 28 29from com.sun.star.reflection.ParamMode import \ 30 IN as PARAM_MODE_IN, \ 31 OUT as PARAM_MODE_OUT, \ 32 INOUT as PARAM_MODE_INOUT 33 34from com.sun.star.beans.PropertyAttribute import \ 35 MAYBEVOID as PROP_ATTR_MAYBEVOID, \ 36 BOUND as PROP_ATTR_BOUND, \ 37 CONSTRAINED as PROP_ATTR_CONSTRAINED, \ 38 TRANSIENT as PROP_ATTR_TRANSIENT, \ 39 READONLY as PROP_ATTR_READONLY, \ 40 MAYBEAMBIGUOUS as PROP_ATTR_MAYBEAMBIGUOUS, \ 41 MAYBEDEFAULT as PROP_ATTR_MAYBEDEFAULT, \ 42 REMOVABLE as PROP_ATTR_REMOVABLE 43 44def _mode_to_str( mode ): 45 ret = "[]" 46 if mode == PARAM_MODE_INOUT: 47 ret = "[inout]" 48 elif mode == PARAM_MODE_OUT: 49 ret = "[out]" 50 elif mode == PARAM_MODE_IN: 51 ret = "[in]" 52 return ret 53 54def _propertymode_to_str( mode ): 55 ret = "" 56 if PROP_ATTR_REMOVABLE & mode: 57 ret = ret + "removable " 58 if PROP_ATTR_MAYBEDEFAULT & mode: 59 ret = ret + "maybedefault " 60 if PROP_ATTR_MAYBEAMBIGUOUS & mode: 61 ret = ret + "maybeambiguous " 62 if PROP_ATTR_READONLY & mode: 63 ret = ret + "readonly " 64 if PROP_ATTR_TRANSIENT & mode: 65 ret = ret + "transient " 66 if PROP_ATTR_CONSTRAINED & mode: 67 ret = ret + "constrained " 68 if PROP_ATTR_BOUND & mode: 69 ret = ret + "bound " 70 if PROP_ATTR_MAYBEVOID & mode: 71 ret = ret + "maybevoid " 72 return ret.rstrip() 73 74def inspect( obj , out ): 75 if isinstance( obj, uno.Type ) or \ 76 isinstance( obj, uno.Char ) or \ 77 isinstance( obj, uno.Bool ) or \ 78 isinstance( obj, uno.ByteSequence ) or \ 79 isinstance( obj, uno.Enum ) or \ 80 isinstance( obj, uno.Any ): 81 out.write( str(obj) + "\n") 82 return 83 84 ctx = uno.getComponentContext() 85 introspection = \ 86 ctx.ServiceManager.createInstanceWithContext( "com.sun.star.beans.Introspection", ctx ) 87 88 out.write( "Supported services:\n" ) 89 if hasattr( obj, "getSupportedServiceNames" ): 90 names = obj.getSupportedServiceNames() 91 for ii in names: 92 out.write( " " + ii + "\n" ) 93 else: 94 out.write( " unknown\n" ) 95 96 out.write( "Interfaces:\n" ) 97 if hasattr( obj, "getTypes" ): 98 interfaces = obj.getTypes() 99 for ii in interfaces: 100 out.write( " " + ii.typeName + "\n" ) 101 else: 102 out.write( " unknown\n" ) 103 104 access = introspection.inspect( obj ) 105 methods = access.getMethods( METHOD_CONCEPT_ALL ) 106 out.write( "Methods:\n" ) 107 for ii in methods: 108 out.write( " " + ii.ReturnType.Name + " " + ii.Name ) 109 args = ii.ParameterTypes 110 infos = ii.ParameterInfos 111 out.write( "( " ) 112 for i in range( 0, len( args ) ): 113 if i > 0: 114 out.write( ", " ) 115 out.write( _mode_to_str( infos[i].aMode ) + " " + args[i].Name + " " + infos[i].aName ) 116 out.write( " )\n" ) 117 118 props = access.getProperties( PROPERTY_CONCEPT_ALL ) 119 out.write ("Properties:\n" ) 120 for ii in props: 121 out.write( " ("+_propertymode_to_str( ii.Attributes ) + ") "+ii.Type.typeName+" "+ii.Name+ "\n" ) 122 123def createSingleServiceFactory( clazz, implementationName, serviceNames ): 124 return _FactoryHelper_( clazz, implementationName, serviceNames ) 125 126class _ImplementationHelperEntry: 127 def __init__(self, ctor,serviceNames): 128 self.ctor = ctor 129 self.serviceNames = serviceNames 130 131class ImplementationHelper: 132 def __init__(self): 133 self.impls = {} 134 135 def addImplementation( self, ctor, implementationName, serviceNames ): 136 self.impls[implementationName] = _ImplementationHelperEntry(ctor,serviceNames) 137 138 def writeRegistryInfo( self, regKey, smgr ): 139 for i in list(self.impls.items()): 140 keyName = "/"+ i[0] + "/UNO/SERVICES" 141 key = regKey.createKey( keyName ) 142 for serviceName in i[1].serviceNames: 143 key.createKey( serviceName ) 144 return 1 145 146 def getComponentFactory( self, implementationName , regKey, smgr ): 147 entry = self.impls.get( implementationName, None ) 148 if entry is None: 149 raise RuntimeException( implementationName + " is unknown" , None ) 150 return createSingleServiceFactory( entry.ctor, implementationName, entry.serviceNames ) 151 152 def getSupportedServiceNames( self, implementationName ): 153 entry = self.impls.get( implementationName, None ) 154 if entry is None: 155 raise RuntimeException( implementationName + " is unknown" , None ) 156 return entry.serviceNames 157 158 def supportsService( self, implementationName, serviceName ): 159 entry = self.impls.get( implementationName,None ) 160 if entry is None: 161 raise RuntimeException( implementationName + " is unknown", None ) 162 return serviceName in entry.serviceNames 163 164 165class ImplementationEntry: 166 def __init__(self, implName, supportedServices, clazz ): 167 self.implName = implName 168 self.supportedServices = supportedServices 169 self.clazz = clazz 170 171def writeRegistryInfoHelper( smgr, regKey, seqEntries ): 172 for entry in seqEntries: 173 keyName = "/"+ entry.implName + "/UNO/SERVICES" 174 key = regKey.createKey( keyName ) 175 for serviceName in entry.supportedServices: 176 key.createKey( serviceName ) 177 178def systemPathToFileUrl( systemPath ): 179 "returns a file-url for the given system path" 180 return pyuno.systemPathToFileUrl( systemPath ) 181 182def fileUrlToSystemPath( url ): 183 "returns a system path (determined by the system, the python interpreter is running on)" 184 return pyuno.fileUrlToSystemPath( url ) 185 186def absolutize( path, relativeUrl ): 187 "returns an absolute file url from the given urls" 188 return pyuno.absolutize( path, relativeUrl ) 189 190def getComponentFactoryHelper( implementationName, smgr, regKey, seqEntries ): 191 for x in seqEntries: 192 if x.implName == implementationName: 193 return createSingleServiceFactory( x.clazz, implementationName, x.supportedServices ) 194 195def addComponentsToContext( toBeExtendedContext, contextRuntime, componentUrls, loaderName ): 196 smgr = contextRuntime.ServiceManager 197 loader = smgr.createInstanceWithContext( loaderName, contextRuntime ) 198 implReg = smgr.createInstanceWithContext( "com.sun.star.registry.ImplementationRegistration",contextRuntime) 199 200 isWin = os.name == 'nt' or os.name == 'dos' 201 isMac = sys.platform == 'darwin' 202 # create a temporary registry 203 for componentUrl in componentUrls: 204 reg = smgr.createInstanceWithContext( "com.sun.star.registry.SimpleRegistry", contextRuntime ) 205 reg.open( "", 0, 1 ) 206 if not isWin and componentUrl.endswith( ".uno" ): # still allow platform independent naming 207 if isMac: 208 componentUrl = componentUrl + ".dylib" 209 else: 210 componentUrl = componentUrl + ".so" 211 212 implReg.registerImplementation( loaderName,componentUrl, reg ) 213 rootKey = reg.getRootKey() 214 implementationKey = rootKey.openKey( "IMPLEMENTATIONS" ) 215 implNames = implementationKey.getKeyNames() 216 extSMGR = toBeExtendedContext.ServiceManager 217 for x in implNames: 218 fac = loader.activate( max(x.split("/")),"",componentUrl,rootKey) 219 extSMGR.insert( fac ) 220 reg.close() 221 222# never shrinks ! 223_g_typeTable = {} 224def _unohelper_getHandle( self): 225 ret = None 226 if self.__class__ in _g_typeTable: 227 ret = _g_typeTable[self.__class__] 228 else: 229 names = {} 230 traverse = list(self.__class__.__bases__) 231 while len( traverse ) > 0: 232 item = traverse.pop() 233 bases = item.__bases__ 234 if uno.isInterface( item ): 235 names[item.__pyunointerface__] = None 236 elif len(bases) > 0: 237 # the "else if", because we only need the most derived interface 238 traverse = traverse + list(bases)# 239 240 lst = list(names.keys()) 241 types = [] 242 for x in lst: 243 t = uno.getTypeByName( x ) 244 types.append( t ) 245 246 ret = tuple(types) 247 _g_typeTable[self.__class__] = ret 248 return ret 249 250class Base(XTypeProvider): 251 def getTypes( self ): 252 return _unohelper_getHandle( self ) 253 def getImplementationId(self): 254 return () 255 256class CurrentContext(XCurrentContext, Base ): 257 """a current context implementation, which first does a lookup in the given 258 hashmap and if the key cannot be found, it delegates to the predecessor 259 if available 260 """ 261 def __init__( self, oldContext, hashMap ): 262 self.hashMap = hashMap 263 self.oldContext = oldContext 264 265 def getValueByName( self, name ): 266 if name in self.hashMap: 267 return self.hashMap[name] 268 elif self.oldContext is not None: 269 return self.oldContext.getValueByName( name ) 270 else: 271 return None 272 273# ------------------------------------------------- 274# implementation details 275# ------------------------------------------------- 276class _FactoryHelper_( XSingleComponentFactory, XServiceInfo, Base ): 277 def __init__( self, clazz, implementationName, serviceNames ): 278 self.clazz = clazz 279 self.implementationName = implementationName 280 self.serviceNames = serviceNames 281 282 def getImplementationName( self ): 283 return self.implementationName 284 285 def supportsService( self, ServiceName ): 286 return ServiceName in self.serviceNames 287 288 def getSupportedServiceNames( self ): 289 return self.serviceNames 290 291 def createInstanceWithContext( self, context ): 292 return self.clazz( context ) 293 294 def createInstanceWithArgumentsAndContext( self, args, context ): 295 return self.clazz( context, *args ) 296 297# vim: set shiftwidth=4 softtabstop=4 expandtab: 298