xref: /trunk/main/pyuno/source/module/unohelper.py (revision a0428e9e)
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 + "tranient "
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 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 _g_typeTable.has_key( self.__class__ ):
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 = 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
299