306 lines
11 KiB
Python
306 lines
11 KiB
Python
# -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
#*************************************************************************
|
|
#
|
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
#
|
|
# Copyright 2000, 2010 Oracle and/or its affiliates.
|
|
#
|
|
# OpenOffice.org - a multi-platform office productivity suite
|
|
#
|
|
# This file is part of OpenOffice.org.
|
|
#
|
|
# OpenOffice.org is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU Lesser General Public License version 3
|
|
# only, as published by the Free Software Foundation.
|
|
#
|
|
# OpenOffice.org is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Lesser General Public License version 3 for more details
|
|
# (a copy is included in the LICENSE file that accompanied this code).
|
|
#
|
|
# You should have received a copy of the GNU Lesser General Public License
|
|
# version 3 along with OpenOffice.org. If not, see
|
|
# <http://www.openoffice.org/license.html>
|
|
# for a copy of the LGPLv3 License.
|
|
#
|
|
#*************************************************************************
|
|
import uno
|
|
import pyuno
|
|
import os
|
|
import sys
|
|
|
|
from com.sun.star.lang import XTypeProvider, XSingleComponentFactory, XServiceInfo
|
|
from com.sun.star.uno import RuntimeException, XCurrentContext
|
|
from com.sun.star.beans.MethodConcept import ALL as METHOD_CONCEPT_ALL
|
|
from com.sun.star.beans.PropertyConcept import ALL as PROPERTY_CONCEPT_ALL
|
|
|
|
from com.sun.star.reflection.ParamMode import \
|
|
IN as PARAM_MODE_IN, \
|
|
OUT as PARAM_MODE_OUT, \
|
|
INOUT as PARAM_MODE_INOUT
|
|
|
|
from com.sun.star.beans.PropertyAttribute import \
|
|
MAYBEVOID as PROP_ATTR_MAYBEVOID, \
|
|
BOUND as PROP_ATTR_BOUND, \
|
|
CONSTRAINED as PROP_ATTR_CONSTRAINED, \
|
|
TRANSIENT as PROP_ATTR_TRANSIENT, \
|
|
READONLY as PROP_ATTR_READONLY, \
|
|
MAYBEAMBIGUOUS as PROP_ATTR_MAYBEAMBIGUOUS, \
|
|
MAYBEDEFAULT as PROP_ATTR_MAYBEDEFAULT, \
|
|
REMOVEABLE as PROP_ATTR_REMOVEABLE
|
|
|
|
def _mode_to_str( mode ):
|
|
ret = "[]"
|
|
if mode == PARAM_MODE_INOUT:
|
|
ret = "[inout]"
|
|
elif mode == PARAM_MODE_OUT:
|
|
ret = "[out]"
|
|
elif mode == PARAM_MODE_IN:
|
|
ret = "[in]"
|
|
return ret
|
|
|
|
def _propertymode_to_str( mode ):
|
|
ret = ""
|
|
if PROP_ATTR_REMOVEABLE & mode:
|
|
ret = ret + "removeable "
|
|
if PROP_ATTR_MAYBEDEFAULT & mode:
|
|
ret = ret + "maybedefault "
|
|
if PROP_ATTR_MAYBEAMBIGUOUS & mode:
|
|
ret = ret + "maybeambigous "
|
|
if PROP_ATTR_READONLY & mode:
|
|
ret = ret + "readonly "
|
|
if PROP_ATTR_TRANSIENT & mode:
|
|
ret = ret + "tranient "
|
|
if PROP_ATTR_CONSTRAINED & mode:
|
|
ret = ret + "constrained "
|
|
if PROP_ATTR_BOUND & mode:
|
|
ret = ret + "bound "
|
|
if PROP_ATTR_MAYBEVOID & mode:
|
|
ret = ret + "maybevoid "
|
|
return ret.rstrip()
|
|
|
|
def inspect( obj , out ):
|
|
if isinstance( obj, uno.Type ) or \
|
|
isinstance( obj, uno.Char ) or \
|
|
isinstance( obj, uno.Bool ) or \
|
|
isinstance( obj, uno.ByteSequence ) or \
|
|
isinstance( obj, uno.Enum ) or \
|
|
isinstance( obj, uno.Any ):
|
|
out.write( str(obj) + "\n")
|
|
return
|
|
|
|
ctx = uno.getComponentContext()
|
|
introspection = \
|
|
ctx.ServiceManager.createInstanceWithContext( "com.sun.star.beans.Introspection", ctx )
|
|
|
|
out.write( "Supported services:\n" )
|
|
if hasattr( obj, "getSupportedServiceNames" ):
|
|
names = obj.getSupportedServiceNames()
|
|
for ii in names:
|
|
out.write( " " + ii + "\n" )
|
|
else:
|
|
out.write( " unknown\n" )
|
|
|
|
out.write( "Interfaces:\n" )
|
|
if hasattr( obj, "getTypes" ):
|
|
interfaces = obj.getTypes()
|
|
for ii in interfaces:
|
|
out.write( " " + ii.typeName + "\n" )
|
|
else:
|
|
out.write( " unknown\n" )
|
|
|
|
access = introspection.inspect( obj )
|
|
methods = access.getMethods( METHOD_CONCEPT_ALL )
|
|
out.write( "Methods:\n" )
|
|
for ii in methods:
|
|
out.write( " " + ii.ReturnType.Name + " " + ii.Name )
|
|
args = ii.ParameterTypes
|
|
infos = ii.ParameterInfos
|
|
out.write( "( " )
|
|
for i in range( 0, len( args ) ):
|
|
if i > 0:
|
|
out.write( ", " )
|
|
out.write( _mode_to_str( infos[i].aMode ) + " " + args[i].Name + " " + infos[i].aName )
|
|
out.write( " )\n" )
|
|
|
|
props = access.getProperties( PROPERTY_CONCEPT_ALL )
|
|
out.write ("Properties:\n" )
|
|
for ii in props:
|
|
out.write( " ("+_propertymode_to_str( ii.Attributes ) + ") "+ii.Type.typeName+" "+ii.Name+ "\n" )
|
|
|
|
def createSingleServiceFactory( clazz, implementationName, serviceNames ):
|
|
return _FactoryHelper_( clazz, implementationName, serviceNames )
|
|
|
|
class _ImplementationHelperEntry:
|
|
def __init__(self, ctor,serviceNames):
|
|
self.ctor = ctor
|
|
self.serviceNames = serviceNames
|
|
|
|
class ImplementationHelper:
|
|
def __init__(self):
|
|
self.impls = {}
|
|
|
|
def addImplementation( self, ctor, implementationName, serviceNames ):
|
|
self.impls[implementationName] = _ImplementationHelperEntry(ctor,serviceNames)
|
|
|
|
def writeRegistryInfo( self, regKey, smgr ):
|
|
for i in list(self.impls.items()):
|
|
keyName = "/"+ i[0] + "/UNO/SERVICES"
|
|
key = regKey.createKey( keyName )
|
|
for serviceName in i[1].serviceNames:
|
|
key.createKey( serviceName )
|
|
return 1
|
|
|
|
def getComponentFactory( self, implementationName , regKey, smgr ):
|
|
entry = self.impls.get( implementationName, None )
|
|
if entry == None:
|
|
raise RuntimeException( implementationName + " is unknown" , None )
|
|
return createSingleServiceFactory( entry.ctor, implementationName, entry.serviceNames )
|
|
|
|
def getSupportedServiceNames( self, implementationName ):
|
|
entry = self.impls.get( implementationName, None )
|
|
if entry == None:
|
|
raise RuntimeException( implementationName + " is unknown" , None )
|
|
return entry.serviceNames
|
|
|
|
def supportsService( self, implementationName, serviceName ):
|
|
entry = self.impls.get( implementationName,None )
|
|
if entry == None:
|
|
raise RuntimeException( implementationName + " is unknown", None )
|
|
return serviceName in entry.serviceNames
|
|
|
|
|
|
class ImplementationEntry:
|
|
def __init__(self, implName, supportedServices, clazz ):
|
|
self.implName = implName
|
|
self.supportedServices = supportedServices
|
|
self.clazz = clazz
|
|
|
|
def writeRegistryInfoHelper( smgr, regKey, seqEntries ):
|
|
for entry in seqEntries:
|
|
keyName = "/"+ entry.implName + "/UNO/SERVICES"
|
|
key = regKey.createKey( keyName )
|
|
for serviceName in entry.supportedServices:
|
|
key.createKey( serviceName )
|
|
|
|
def systemPathToFileUrl( systemPath ):
|
|
"returns a file-url for the given system path"
|
|
return pyuno.systemPathToFileUrl( systemPath )
|
|
|
|
def fileUrlToSystemPath( url ):
|
|
"returns a system path (determined by the system, the python interpreter is running on)"
|
|
return pyuno.fileUrlToSystemPath( url )
|
|
|
|
def absolutize( path, relativeUrl ):
|
|
"returns an absolute file url from the given urls"
|
|
return pyuno.absolutize( path, relativeUrl )
|
|
|
|
def getComponentFactoryHelper( implementationName, smgr, regKey, seqEntries ):
|
|
for x in seqEntries:
|
|
if x.implName == implementationName:
|
|
return createSingleServiceFactory( x.clazz, implementationName, x.supportedServices )
|
|
|
|
def addComponentsToContext( toBeExtendedContext, contextRuntime, componentUrls, loaderName ):
|
|
smgr = contextRuntime.ServiceManager
|
|
loader = smgr.createInstanceWithContext( loaderName, contextRuntime )
|
|
implReg = smgr.createInstanceWithContext( "com.sun.star.registry.ImplementationRegistration",contextRuntime)
|
|
|
|
isWin = os.name == 'nt' or os.name == 'dos'
|
|
isMac = sys.platform == 'darwin'
|
|
# create a temporary registry
|
|
for componentUrl in componentUrls:
|
|
reg = smgr.createInstanceWithContext( "com.sun.star.registry.SimpleRegistry", contextRuntime )
|
|
reg.open( "", 0, 1 )
|
|
if not isWin and componentUrl.endswith( ".uno" ): # still allow platform independent naming
|
|
if isMac:
|
|
componentUrl = componentUrl + ".dylib"
|
|
else:
|
|
componentUrl = componentUrl + ".so"
|
|
|
|
implReg.registerImplementation( loaderName,componentUrl, reg )
|
|
rootKey = reg.getRootKey()
|
|
implementationKey = rootKey.openKey( "IMPLEMENTATIONS" )
|
|
implNames = implementationKey.getKeyNames()
|
|
extSMGR = toBeExtendedContext.ServiceManager
|
|
for x in implNames:
|
|
fac = loader.activate( max(x.split("/")),"",componentUrl,rootKey)
|
|
extSMGR.insert( fac )
|
|
reg.close()
|
|
|
|
# never shrinks !
|
|
_g_typeTable = {}
|
|
def _unohelper_getHandle( self):
|
|
ret = None
|
|
if self.__class__ in _g_typeTable:
|
|
ret = _g_typeTable[self.__class__]
|
|
else:
|
|
names = {}
|
|
traverse = list(self.__class__.__bases__)
|
|
while len( traverse ) > 0:
|
|
item = traverse.pop()
|
|
bases = item.__bases__
|
|
if uno.isInterface( item ):
|
|
names[item.__pyunointerface__] = None
|
|
elif len(bases) > 0:
|
|
# the "else if", because we only need the most derived interface
|
|
traverse = traverse + list(bases)#
|
|
|
|
lst = list(names.keys())
|
|
types = []
|
|
for x in lst:
|
|
t = uno.getTypeByName( x )
|
|
types.append( t )
|
|
|
|
ret = tuple(types) , uno.generateUuid()
|
|
_g_typeTable[self.__class__] = ret
|
|
return ret
|
|
|
|
class Base(XTypeProvider):
|
|
def getTypes( self ):
|
|
return _unohelper_getHandle( self )[0]
|
|
def getImplementationId(self):
|
|
return _unohelper_getHandle( self )[1]
|
|
|
|
class CurrentContext(XCurrentContext, Base ):
|
|
"""a current context implementation, which first does a lookup in the given
|
|
hashmap and if the key cannot be found, it delegates to the predecessor
|
|
if available
|
|
"""
|
|
def __init__( self, oldContext, hashMap ):
|
|
self.hashMap = hashMap
|
|
self.oldContext = oldContext
|
|
|
|
def getValueByName( self, name ):
|
|
if name in self.hashMap:
|
|
return self.hashMap[name]
|
|
elif self.oldContext != None:
|
|
return self.oldContext.getValueByName( name )
|
|
else:
|
|
return None
|
|
|
|
# -------------------------------------------------
|
|
# implementation details
|
|
# -------------------------------------------------
|
|
class _FactoryHelper_( XSingleComponentFactory, XServiceInfo, Base ):
|
|
def __init__( self, clazz, implementationName, serviceNames ):
|
|
self.clazz = clazz
|
|
self.implementationName = implementationName
|
|
self.serviceNames = serviceNames
|
|
|
|
def getImplementationName( self ):
|
|
return self.implementationName
|
|
|
|
def supportsService( self, ServiceName ):
|
|
return ServiceName in self.serviceNames
|
|
|
|
def getSupportedServiceNames( self ):
|
|
return self.serviceNames
|
|
|
|
def createInstanceWithContext( self, context ):
|
|
return self.clazz( context )
|
|
|
|
def createInstanceWithArgumentsAndContext( self, args, context ):
|
|
return self.clazz( context, *args )
|
|
|
|
# vim:set shiftwidth=4 softtabstop=4 expandtab:
|