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  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_stoc.hxx"
26 #include <osl/diagnose.h>
27 #include <rtl/ustrbuf.hxx>
28 #include <com/sun/star/beans/PropertyAttribute.hpp>
29 #include "com/sun/star/uno/RuntimeException.hpp"
30 
31 #include "registry/reader.hxx"
32 #include "registry/version.h"
33 #include "base.hxx"
34 #include "methoddescription.hxx"
35 
36 #include <memory>
37 
38 using namespace com::sun::star;
39 
40 namespace {
41 
42 class Constructor:
43     public cppu::WeakImplHelper1< XServiceConstructorDescription >
44 {
45 public:
Constructor(Reference<XHierarchicalNameAccess> const & manager,rtl::OUString const & name,Sequence<sal_Int8> const & bytes,sal_uInt16 index)46     Constructor(
47         Reference< XHierarchicalNameAccess > const & manager,
48         rtl::OUString const & name, Sequence< sal_Int8 > const & bytes,
49         sal_uInt16 index):
50         m_desc(manager, name, bytes, index) {}
51 
~Constructor()52     virtual ~Constructor() {}
53 
isDefaultConstructor()54     virtual sal_Bool SAL_CALL isDefaultConstructor() throw (RuntimeException)
55     { return m_desc.getName().getLength() == 0; }
56 
getName()57     virtual rtl::OUString SAL_CALL getName() throw (RuntimeException)
58     { return m_desc.getName(); }
59 
getParameters()60     virtual Sequence< Reference< XParameter > > SAL_CALL getParameters()
61         throw (RuntimeException)
62     { return m_desc.getParameters(); }
63 
64     virtual Sequence< Reference<XCompoundTypeDescription > > SAL_CALL
getExceptions()65     getExceptions() throw (RuntimeException)
66     { return m_desc.getExceptions(); }
67 
68 private:
69     Constructor(Constructor &); // not implemented
70     void operator =(Constructor); // not implemented
71 
72     stoc::registry_tdprovider::MethodDescription m_desc;
73 };
74 
75 }
76 
77 namespace stoc_rdbtdp
78 {
79 
80 //==================================================================================================
81 //
82 // class PropertyTypeDescriptionImpl
83 //
84 //==================================================================================================
85 class PropertyTypeDescriptionImpl : public WeakImplHelper1< XPropertyTypeDescription >
86 {
87     OUString                      _aName;
88     Reference< XTypeDescription > _xTD;
89     sal_Int16                     _nFlags;
90 
91 public:
PropertyTypeDescriptionImpl(const OUString & rName,const Reference<XTypeDescription> & xTD,sal_Int16 nFlags)92     PropertyTypeDescriptionImpl( const OUString & rName,
93                                  const Reference< XTypeDescription > & xTD,
94                                  sal_Int16 nFlags )
95     : _aName( rName ), _xTD( xTD ), _nFlags( nFlags )
96     {
97         g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
98     }
99     virtual ~PropertyTypeDescriptionImpl();
100 
101     // XTypeDescription
102     virtual TypeClass SAL_CALL getTypeClass()
103         throw( RuntimeException );
104     virtual OUString SAL_CALL getName()
105         throw( RuntimeException );
106 
107     // XPropertyTypeDescription
108     virtual sal_Int16 SAL_CALL getPropertyFlags()
109         throw ( RuntimeException );
110     virtual Reference< XTypeDescription > SAL_CALL getPropertyTypeDescription()
111         throw ( RuntimeException );
112 };
113 
114 //__________________________________________________________________________________________________
115 // virtual
~PropertyTypeDescriptionImpl()116 PropertyTypeDescriptionImpl::~PropertyTypeDescriptionImpl()
117 {
118     g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
119 }
120 
121 // XTypeDescription
122 //__________________________________________________________________________________________________
123 // virtual
getTypeClass()124 TypeClass PropertyTypeDescriptionImpl::getTypeClass()
125     throw ( RuntimeException )
126 {
127     return TypeClass_PROPERTY;
128 }
129 //__________________________________________________________________________________________________
130 // virtual
getName()131 OUString PropertyTypeDescriptionImpl::getName()
132     throw ( RuntimeException )
133 {
134     return _aName;
135 }
136 
137 // XPropertyTypeDescription
138 //__________________________________________________________________________________________________
139 // virtual
getPropertyFlags()140 sal_Int16 SAL_CALL PropertyTypeDescriptionImpl::getPropertyFlags()
141     throw ( RuntimeException )
142 {
143     return _nFlags;
144 }
145 
146 //__________________________________________________________________________________________________
147 // virtual
148 Reference< XTypeDescription > SAL_CALL
getPropertyTypeDescription()149 PropertyTypeDescriptionImpl::getPropertyTypeDescription()
150     throw ( RuntimeException )
151 {
152     return _xTD;
153 }
154 
155 //==================================================================================================
156 //
157 // ServiceTypeDescriptionImpl implementation
158 //
159 //==================================================================================================
160 
161 //__________________________________________________________________________________________________
162 // virtual
~ServiceTypeDescriptionImpl()163 ServiceTypeDescriptionImpl::~ServiceTypeDescriptionImpl()
164 {
165 	g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
166 }
167 
168 // XTypeDescription
169 //__________________________________________________________________________________________________
170 // virtual
getTypeClass()171 TypeClass ServiceTypeDescriptionImpl::getTypeClass()
172 	throw(::com::sun::star::uno::RuntimeException)
173 {
174     return TypeClass_SERVICE;
175 }
176 //__________________________________________________________________________________________________
177 // virtual
getName()178 OUString ServiceTypeDescriptionImpl::getName()
179 	throw(::com::sun::star::uno::RuntimeException)
180 {
181 	return _aName;
182 }
183 
184 // XServiceTypeDescription
185 //__________________________________________________________________________________________________
186 // virtual
187 Sequence< Reference< XServiceTypeDescription > > SAL_CALL
getMandatoryServices()188 ServiceTypeDescriptionImpl::getMandatoryServices()
189     throw ( RuntimeException )
190 {
191     getReferences();
192     return _aMandatoryServices;
193 }
194 
195 //__________________________________________________________________________________________________
196 // virtual
197 Sequence< Reference< XServiceTypeDescription > > SAL_CALL
getOptionalServices()198 ServiceTypeDescriptionImpl::getOptionalServices()
199     throw ( RuntimeException )
200 {
201     getReferences();
202     return _aOptionalServices;
203 }
204 
205 //__________________________________________________________________________________________________
206 // virtual
207 Sequence< Reference< XInterfaceTypeDescription > > SAL_CALL
getMandatoryInterfaces()208 ServiceTypeDescriptionImpl::getMandatoryInterfaces()
209     throw ( RuntimeException )
210 {
211     getReferences();
212     return _aMandatoryInterfaces;
213 }
214 
215 //__________________________________________________________________________________________________
216 // virtual
217 Sequence< Reference< XInterfaceTypeDescription > > SAL_CALL
getOptionalInterfaces()218 ServiceTypeDescriptionImpl::getOptionalInterfaces()
219     throw ( RuntimeException )
220 {
221     getReferences();
222     return _aOptionalInterfaces;
223 }
224 
225 //__________________________________________________________________________________________________
226 // virtual
227 Sequence< Reference< XPropertyTypeDescription > > SAL_CALL
getProperties()228 ServiceTypeDescriptionImpl::getProperties()
229     throw ( RuntimeException )
230 {
231     {
232         MutexGuard guard(getMutex());
233         if (_pProps.get() != 0) {
234             return *_pProps;
235         }
236     }
237 
238     typereg::Reader aReader(
239         _aBytes.getConstArray(), _aBytes.getLength(), false, TYPEREG_VERSION_1);
240 
241     sal_uInt16 nFields = (sal_uInt16)aReader.getFieldCount();
242     std::auto_ptr< Sequence< Reference< XPropertyTypeDescription > > >
243         pTempProps(
244             new Sequence< Reference< XPropertyTypeDescription > >(nFields));
245     Reference< XPropertyTypeDescription > * pProps = pTempProps->getArray();
246 
247     while ( nFields-- )
248     {
249         // name
250         OUStringBuffer aName( _aName );
251         aName.appendAscii( "." );
252         aName.append( aReader.getFieldName( nFields ) );
253 
254         // type description
255         Reference< XTypeDescription > xTD;
256         try
257         {
258             _xTDMgr->getByHierarchicalName(
259                 aReader.getFieldTypeName( nFields ).replace( '/', '.' ) )
260                     >>= xTD;
261         }
262         catch ( NoSuchElementException const & )
263         {
264         }
265         OSL_ENSURE( xTD.is(), "### no type description for property!" );
266 
267         // flags
268         RTFieldAccess nFlags = aReader.getFieldFlags( nFields );
269 
270         sal_Int16 nAttribs = 0;
271         if ( nFlags & RT_ACCESS_READONLY )
272             nAttribs |= beans::PropertyAttribute::READONLY;
273         if ( nFlags & RT_ACCESS_OPTIONAL )
274             nAttribs |= beans::PropertyAttribute::OPTIONAL;
275         if ( nFlags & RT_ACCESS_MAYBEVOID )
276             nAttribs |= beans::PropertyAttribute::MAYBEVOID;
277         if ( nFlags & RT_ACCESS_BOUND )
278             nAttribs |= beans::PropertyAttribute::BOUND;
279         if ( nFlags & RT_ACCESS_CONSTRAINED )
280             nAttribs |= beans::PropertyAttribute::CONSTRAINED;
281         if ( nFlags & RT_ACCESS_TRANSIENT )
282             nAttribs |= beans::PropertyAttribute::TRANSIENT;
283         if ( nFlags & RT_ACCESS_MAYBEAMBIGUOUS )
284             nAttribs |= beans::PropertyAttribute::MAYBEAMBIGUOUS;
285         if ( nFlags & RT_ACCESS_MAYBEDEFAULT )
286             nAttribs |= beans::PropertyAttribute::MAYBEDEFAULT;
287         if ( nFlags & RT_ACCESS_REMOVEABLE )
288             nAttribs |= beans::PropertyAttribute::REMOVEABLE;
289 
290         OSL_ENSURE( !(nFlags & RT_ACCESS_PROPERTY),
291                     "### RT_ACCESS_PROPERTY is unexpected here!" );
292         OSL_ENSURE( !(nFlags & RT_ACCESS_ATTRIBUTE),
293                     "### RT_ACCESS_ATTRIBUTE is unexpected here!" );
294         OSL_ENSURE( !(nFlags & RT_ACCESS_CONST),
295                     "### RT_ACCESS_CONST is unexpected here!" );
296         // always set, unless RT_ACCESS_READONLY is set.
297         //OSL_ENSURE( !(nFlags & RT_ACCESS_READWRITE),
298         //            "### RT_ACCESS_READWRITE is unexpected here" );
299         OSL_ENSURE( !(nFlags & RT_ACCESS_DEFAULT),
300                     "### RT_ACCESS_DEAFAULT is unexpected here" );
301 
302         pProps[ nFields ]
303             = new PropertyTypeDescriptionImpl( aName.makeStringAndClear(),
304                                                xTD,
305                                                nAttribs );
306     }
307 
308     MutexGuard guard(getMutex());
309     if (_pProps.get() == 0) {
310         _pProps = pTempProps;
311     }
312     return *_pProps;
313 }
314 
isSingleInterfaceBased()315 sal_Bool ServiceTypeDescriptionImpl::isSingleInterfaceBased()
316     throw (RuntimeException)
317 {
318     getReferences();
319     return _xInterfaceTD.is();
320 }
321 
getInterface()322 Reference< XTypeDescription > ServiceTypeDescriptionImpl::getInterface()
323     throw (RuntimeException)
324 {
325     getReferences();
326     return _xInterfaceTD;
327 }
328 
329 Sequence< Reference< XServiceConstructorDescription > >
getConstructors()330 ServiceTypeDescriptionImpl::getConstructors() throw (RuntimeException) {
331     MutexGuard guard(getMutex());
332     if (_pCtors.get() == 0) {
333         typereg::Reader reader(
334             _aBytes.getConstArray(), _aBytes.getLength(), false,
335             TYPEREG_VERSION_1);
336         sal_uInt16 ctorCount = reader.getMethodCount();
337         std::auto_ptr< Sequence< Reference< XServiceConstructorDescription > > >
338             ctors(
339                 new Sequence< Reference< XServiceConstructorDescription > >(
340                     ctorCount));
341         for (sal_uInt16 i = 0; i < ctorCount; ++i) {
342             rtl::OUString name(reader.getMethodName(i));
343             if (reader.getMethodFlags(i) != RT_MODE_TWOWAY
344                 || (!reader.getMethodReturnTypeName(i).equalsAsciiL(
345                         RTL_CONSTASCII_STRINGPARAM("void")))
346                 || (name.getLength() == 0
347                     && (ctorCount != 1 || reader.getMethodParameterCount(i) != 0
348                         || reader.getMethodExceptionCount(i) != 0)))
349             {
350                 throw RuntimeException(
351                     rtl::OUString(
352                         RTL_CONSTASCII_USTRINGPARAM(
353                             "Service has bad constructors")),
354                     static_cast< OWeakObject * >(this));
355             }
356             (*ctors)[i] = new Constructor(
357                 _xTDMgr, reader.getMethodName(i), _aBytes, i);
358         }
359         _pCtors = ctors;
360     }
361     return *_pCtors;
362 }
363 
364 //__________________________________________________________________________________________________
getReferences()365 void ServiceTypeDescriptionImpl::getReferences()
366     throw ( RuntimeException )
367 {
368     {
369         MutexGuard guard(getMutex());
370         if (_bInitReferences) {
371             return;
372         }
373     }
374     typereg::Reader aReader(
375         _aBytes.getConstArray(), _aBytes.getLength(), false, TYPEREG_VERSION_1);
376     sal_uInt16 superTypes = aReader.getSuperTypeCount();
377     if (superTypes > 1) {
378         throw RuntimeException(
379             rtl::OUString(
380                 RTL_CONSTASCII_USTRINGPARAM(
381                     "Service has more than one supertype")),
382             static_cast< OWeakObject * >(this));
383     }
384     if (superTypes == 1) {
385         OUString aBaseName( aReader.getSuperTypeName(0).replace( '/', '.' ) );
386         if ( aReader.getReferenceCount() != 0
387              || aReader.getFieldCount() != 0 )
388             throw RuntimeException(
389                 OUString(
390                     RTL_CONSTASCII_USTRINGPARAM(
391                         "Service is single-interface--based but also has"
392                         " references and/or properties" ) ),
393                 static_cast< OWeakObject * >( this ) );
394         Reference< XTypeDescription > ifc;
395         try
396         {
397             _xTDMgr->getByHierarchicalName( aBaseName ) >>= ifc;
398         }
399         catch ( NoSuchElementException const & e )
400         {
401             throw RuntimeException(
402                 OUString(
403                     RTL_CONSTASCII_USTRINGPARAM(
404                         "com.sun.star.container.NoSuchElementException: " ) )
405                 + e.Message,
406                 static_cast< OWeakObject * >( this ) );
407         }
408         OSL_ASSERT(ifc.is());
409         if (resolveTypedefs(ifc)->getTypeClass() != TypeClass_INTERFACE) {
410             throw RuntimeException(
411                 OUString(
412                     RTL_CONSTASCII_USTRINGPARAM(
413                         "Single-interface--based service is not based on"
414                         " interface type" ) ),
415                 static_cast< OWeakObject * >( this ) );
416         }
417         MutexGuard guard(getMutex());
418         if (!_bInitReferences) {
419             _xInterfaceTD = ifc;
420             _bInitReferences = true;
421         }
422     }
423     else
424     {
425         sal_uInt16 nRefs = aReader.getReferenceCount();
426         Sequence< Reference< XServiceTypeDescription > > aMandatoryServices(
427             nRefs);
428         Sequence< Reference< XServiceTypeDescription > > aOptionalServices(
429             nRefs);
430         Sequence< Reference< XInterfaceTypeDescription > > aMandatoryInterfaces(
431             nRefs);
432         Sequence< Reference< XInterfaceTypeDescription > > aOptionalInterfaces(
433             nRefs);
434         sal_uInt32 nMS = 0;
435         sal_uInt32 nOS = 0;
436         sal_uInt32 nMI = 0;
437         sal_uInt32 nOI = 0;
438 
439         for ( sal_uInt16 nPos = 0; nPos < nRefs; ++nPos )
440         {
441             RTReferenceType eType = aReader.getReferenceSort( nPos );
442             switch ( eType )
443             {
444             case RT_REF_EXPORTS: // service
445                 {
446                     uno::Any aTypeDesc;
447                     try
448                     {
449                         aTypeDesc = _xTDMgr->getByHierarchicalName(
450                             aReader.getReferenceTypeName( nPos ).replace(
451                                 '/', '.' ) );
452                     }
453                     catch ( NoSuchElementException const & e )
454                     {
455                         throw RuntimeException(
456                             OUString(
457                                 RTL_CONSTASCII_USTRINGPARAM(
458                                     "com.sun.star.container."
459                                     "NoSuchElementException: " ) )
460                             + e.Message,
461                             static_cast< OWeakObject * >( this ) );
462                     }
463 
464                     RTFieldAccess nAccess = aReader.getReferenceFlags( nPos );
465                     if ( nAccess & RT_ACCESS_OPTIONAL )
466                     {
467                         // optional service
468                         if ( !( aTypeDesc >>= aOptionalServices[ nOS ] ) )
469                             throw RuntimeException(
470                                 OUString(
471                                     RTL_CONSTASCII_USTRINGPARAM(
472                                         "Service 'export' is not a service" ) ),
473                                 static_cast< OWeakObject * >( this ) );
474                         nOS++;
475                     }
476                     else
477                     {
478                         // mandatory service
479                         if ( !( aTypeDesc >>= aMandatoryServices[ nMS ] ) )
480                             throw RuntimeException(
481                                 OUString(
482                                     RTL_CONSTASCII_USTRINGPARAM(
483                                         "Service 'export' is not a service" ) ),
484                                 static_cast< OWeakObject * >( this ) );
485                         nMS++;
486                     }
487                     break;
488                 }
489             case RT_REF_SUPPORTS: // interface
490                 {
491                     uno::Any aTypeDesc;
492                     try
493                     {
494                         aTypeDesc = _xTDMgr->getByHierarchicalName(
495                             aReader.getReferenceTypeName( nPos ).replace(
496                                 '/', '.' ) );
497                     }
498                     catch ( NoSuchElementException const & e )
499                     {
500                         throw RuntimeException(
501                             OUString(
502                                 RTL_CONSTASCII_USTRINGPARAM(
503                                     "com.sun.star.container."
504                                     "NoSuchElementException: " ) )
505                             + e.Message,
506                             static_cast< OWeakObject * >( this ) );
507                     }
508 
509                     RTFieldAccess nAccess = aReader.getReferenceFlags( nPos );
510                     if ( nAccess & RT_ACCESS_OPTIONAL )
511                     {
512                         // optional interface
513                         if ( !( aTypeDesc >>= aOptionalInterfaces[ nOI ] ) )
514                             throw RuntimeException(
515                                 OUString(
516                                     RTL_CONSTASCII_USTRINGPARAM(
517                                         "Service 'supports' is not an"
518                                         " interface" ) ),
519                                 static_cast< OWeakObject * >( this ) );
520                         nOI++;
521                     }
522                     else
523                     {
524                         // mandatory interface
525                         if ( !( aTypeDesc >>= aMandatoryInterfaces[ nMI ] ) )
526                             throw RuntimeException(
527                                 OUString(
528                                     RTL_CONSTASCII_USTRINGPARAM(
529                                         "Service 'supports' is not an"
530                                         " interface" ) ),
531                                 static_cast< OWeakObject * >( this ) );
532                         nMI++;
533                     }
534                     break;
535                 }
536             case RT_REF_OBSERVES:
537             case RT_REF_NEEDS:
538                 break;
539             default:
540                 OSL_ENSURE( sal_False, "### unsupported reference type!" );
541                 break;
542             }
543         }
544         aMandatoryServices.realloc( nMS );
545         aOptionalServices.realloc( nOS );
546         aMandatoryInterfaces.realloc( nMI );
547         aOptionalInterfaces.realloc( nOI );
548 
549         MutexGuard guard(getMutex());
550         if (!_bInitReferences) {
551             _aMandatoryServices = aMandatoryServices;
552             _aOptionalServices = aOptionalServices;
553             _aMandatoryInterfaces = aMandatoryInterfaces;
554             _aOptionalInterfaces = aOptionalInterfaces;
555             _bInitReferences = true;
556         }
557     }
558 }
559 
560 
561 }
562