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