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