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