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 "registry/reader.hxx"
33 #include "registry/version.h"
34 
35 #include <com/sun/star/reflection/XInterfaceMemberTypeDescription.hpp>
36 #include <com/sun/star/reflection/XInterfaceAttributeTypeDescription2.hpp>
37 #include <com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp>
38 #include <com/sun/star/reflection/XMethodParameter.hpp>
39 #include <com/sun/star/reflection/XParameter.hpp>
40 #include "com/sun/star/uno/RuntimeException.hpp"
41 #include "base.hxx"
42 #include "functiondescription.hxx"
43 #include "methoddescription.hxx"
44 
45 #include <memory>
46 #include <set>
47 
48 namespace stoc_rdbtdp
49 {
50 
51 //==================================================================================================
52 class InterfaceMethodImpl : public WeakImplHelper1< XInterfaceMethodTypeDescription >
53 {
54     stoc::registry_tdprovider::MethodDescription _desc;
55 
56 	Reference< XHierarchicalNameAccess >  _xTDMgr;
57 
58 	OUString							  _aTypeName;
59 
60 	OUString							  _aReturnType;
61 	Reference< XTypeDescription >		  _xReturnTD;
62 
63 	sal_Bool							  _bIsOneWay;
64 	sal_Int32							  _nPosition;
65 
66 public:
67 	InterfaceMethodImpl( const Reference< XHierarchicalNameAccess > & xTDMgr,
68 						 const OUString & rTypeName,
69 						 const OUString & rMemberName,
70 						 const OUString & rReturnType,
71 						 const Sequence< sal_Int8 > & rBytes,
72 						 sal_uInt16 nMethodIndex,
73 						 sal_Bool bIsOneWay,
74 						 sal_Int32 nPosition )
75 		: _desc(xTDMgr, rMemberName, rBytes, nMethodIndex)
76         , _xTDMgr( xTDMgr )
77 		, _aTypeName( rTypeName )
78 		, _aReturnType( rReturnType )
79 		, _bIsOneWay( bIsOneWay )
80 		, _nPosition( nPosition )
81 		{
82 			g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
83 		}
84 	virtual ~InterfaceMethodImpl();
85 
86 	// XTypeDescription
87     virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException);
88     virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException);
89 
90 	// XInterfaceMemberTypeDescription
91     virtual OUString SAL_CALL getMemberName() throw(::com::sun::star::uno::RuntimeException)
92     { return _desc.getName(); }
93     virtual sal_Int32 SAL_CALL getPosition() throw(::com::sun::star::uno::RuntimeException);
94 
95 	// XInterfaceMethodTypeDescription
96 	virtual Reference< XTypeDescription > SAL_CALL getReturnType() throw(::com::sun::star::uno::RuntimeException);
97     virtual sal_Bool SAL_CALL isOneway() throw(::com::sun::star::uno::RuntimeException);
98     virtual Sequence< Reference< XMethodParameter > > SAL_CALL getParameters() throw(::com::sun::star::uno::RuntimeException);
99     virtual Sequence< Reference< XTypeDescription > > SAL_CALL getExceptions() throw(::com::sun::star::uno::RuntimeException);
100 };
101 //__________________________________________________________________________________________________
102 InterfaceMethodImpl::~InterfaceMethodImpl()
103 {
104 	g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
105 }
106 
107 // XTypeDescription
108 //__________________________________________________________________________________________________
109 TypeClass InterfaceMethodImpl::getTypeClass()
110 	throw(::com::sun::star::uno::RuntimeException)
111 {
112 	return TypeClass_INTERFACE_METHOD;
113 }
114 //__________________________________________________________________________________________________
115 OUString InterfaceMethodImpl::getName()
116 	throw(::com::sun::star::uno::RuntimeException)
117 {
118 	return _aTypeName;
119 }
120 
121 // XInterfaceMemberTypeDescription
122 //__________________________________________________________________________________________________
123 sal_Int32 InterfaceMethodImpl::getPosition()
124 	throw(::com::sun::star::uno::RuntimeException)
125 {
126 	return _nPosition;
127 }
128 
129 // XInterfaceMethodTypeDescription
130 //__________________________________________________________________________________________________
131 Reference<XTypeDescription > InterfaceMethodImpl::getReturnType()
132 	throw(::com::sun::star::uno::RuntimeException)
133 {
134 	if (!_xReturnTD.is() && _aReturnType.getLength())
135 	{
136         try
137         {
138             Reference< XTypeDescription > xReturnTD;
139             if (_xTDMgr->getByHierarchicalName( _aReturnType ) >>= xReturnTD)
140             {
141                 MutexGuard aGuard( getMutex() );
142                 if (! _xReturnTD.is())
143                     _xReturnTD = xReturnTD;
144                 return _xReturnTD;
145             }
146         }
147         catch (NoSuchElementException &)
148         {
149         }
150         // never try again, if no td was found
151         _aReturnType = OUString();
152 	}
153 	return _xReturnTD;
154 }
155 //__________________________________________________________________________________________________
156 sal_Bool InterfaceMethodImpl::isOneway()
157 	throw(::com::sun::star::uno::RuntimeException)
158 {
159 	return _bIsOneWay;
160 }
161 //__________________________________________________________________________________________________
162 Sequence<Reference<XMethodParameter > > InterfaceMethodImpl::getParameters()
163 	throw(::com::sun::star::uno::RuntimeException)
164 {
165     Sequence< Reference< XParameter > > s1(_desc.getParameters());
166     Sequence< Reference< XMethodParameter > > s2(s1.getLength());
167     for (sal_Int32 i = 0; i < s1.getLength(); ++i) {
168         s2[i] = s1[i].get();
169     }
170     return s2;
171 }
172 //__________________________________________________________________________________________________
173 Sequence<Reference<XTypeDescription > > InterfaceMethodImpl::getExceptions()
174 	throw(::com::sun::star::uno::RuntimeException)
175 {
176     Sequence< Reference< XCompoundTypeDescription > > s1(
177         _desc.getExceptions());
178     Sequence< Reference< XTypeDescription > > s2(s1.getLength());
179     for (sal_Int32 i = 0; i < s1.getLength(); ++i) {
180         s2[i] = s1[i].get();
181     }
182     return s2;
183 }
184 
185 
186 //##################################################################################################
187 //##################################################################################################
188 //##################################################################################################
189 
190 
191 //==================================================================================================
192 class InterfaceAttributeImpl : public WeakImplHelper1< XInterfaceAttributeTypeDescription2 >
193 {
194 	Reference< XHierarchicalNameAccess >  _xTDMgr;
195 
196 	OUString							  _aTypeName;
197 	OUString							  _aMemberName;
198 
199 	OUString							  _aMemberTypeName;
200 	Reference< XTypeDescription >		  _xMemberTD;
201 
202 	sal_Bool							  _bReadOnly;
203 	sal_Bool							  _bBound;
204 	sal_Int32							  _nPosition;
205 
206     std::auto_ptr< stoc::registry_tdprovider::FunctionDescription > _getter;
207     std::auto_ptr< stoc::registry_tdprovider::FunctionDescription > _setter;
208 
209 public:
210 	InterfaceAttributeImpl(
211         const Reference< XHierarchicalNameAccess > & xTDMgr,
212         const OUString & rTypeName,
213         const OUString & rMemberName,
214         const OUString & rMemberTypeName,
215         sal_Bool bReadOnly,
216         sal_Bool bBound,
217         std::auto_ptr< stoc::registry_tdprovider::FunctionDescription > &
218             getter,
219         std::auto_ptr< stoc::registry_tdprovider::FunctionDescription > &
220             setter,
221         sal_Int32 nPosition )
222 		: _xTDMgr( xTDMgr )
223 		, _aTypeName( rTypeName )
224 		, _aMemberName( rMemberName )
225 		, _aMemberTypeName( rMemberTypeName )
226 		, _bReadOnly( bReadOnly )
227 		, _bBound( bBound )
228 		, _nPosition( nPosition )
229         , _getter( getter )
230         , _setter( setter )
231 		{
232 			g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
233 		}
234 	virtual ~InterfaceAttributeImpl();
235 
236 	// XTypeDescription
237     virtual TypeClass SAL_CALL getTypeClass() throw(::com::sun::star::uno::RuntimeException);
238     virtual OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException);
239 
240 	// XInterfaceMemberTypeDescription
241     virtual OUString SAL_CALL getMemberName() throw(::com::sun::star::uno::RuntimeException);
242     virtual sal_Int32 SAL_CALL getPosition() throw(::com::sun::star::uno::RuntimeException);
243 
244 	// XInterfaceAttributeTypeDescription2
245 	virtual sal_Bool SAL_CALL isReadOnly() throw(::com::sun::star::uno::RuntimeException);
246 	virtual Reference< XTypeDescription > SAL_CALL getType() throw(::com::sun::star::uno::RuntimeException);
247 
248     virtual sal_Bool SAL_CALL isBound() throw (RuntimeException)
249     { return _bBound; }
250 
251     virtual Sequence< Reference< XCompoundTypeDescription > > SAL_CALL
252     getGetExceptions() throw (RuntimeException)
253     {
254         if (_getter.get() != 0) {
255             return _getter->getExceptions();
256         } else {
257             return Sequence< Reference< XCompoundTypeDescription > >();
258         }
259     }
260 
261     virtual Sequence< Reference< XCompoundTypeDescription > > SAL_CALL
262     getSetExceptions() throw (RuntimeException)
263     {
264         if (_setter.get() != 0) {
265             return _setter->getExceptions();
266         } else {
267             return Sequence< Reference< XCompoundTypeDescription > >();
268         }
269     }
270 };
271 
272 InterfaceAttributeImpl::~InterfaceAttributeImpl()
273 {
274 	g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
275 }
276 // XTypeDescription
277 //__________________________________________________________________________________________________
278 TypeClass InterfaceAttributeImpl::getTypeClass()
279 	throw(::com::sun::star::uno::RuntimeException)
280 {
281 	return TypeClass_INTERFACE_ATTRIBUTE;
282 }
283 //__________________________________________________________________________________________________
284 OUString InterfaceAttributeImpl::getName()
285 	throw(::com::sun::star::uno::RuntimeException)
286 {
287 	return _aTypeName;
288 }
289 
290 // XInterfaceMemberTypeDescription
291 //__________________________________________________________________________________________________
292 OUString InterfaceAttributeImpl::getMemberName()
293 	throw(::com::sun::star::uno::RuntimeException)
294 {
295 	return _aMemberName;
296 }
297 //__________________________________________________________________________________________________
298 sal_Int32 InterfaceAttributeImpl::getPosition()
299 	throw(::com::sun::star::uno::RuntimeException)
300 {
301 	return _nPosition;
302 }
303 
304 // XInterfaceAttributeTypeDescription2
305 //__________________________________________________________________________________________________
306 sal_Bool InterfaceAttributeImpl::isReadOnly()
307 	throw(::com::sun::star::uno::RuntimeException)
308 {
309 	return _bReadOnly;
310 }
311 //__________________________________________________________________________________________________
312 Reference<XTypeDescription > InterfaceAttributeImpl::getType()
313 	throw(::com::sun::star::uno::RuntimeException)
314 {
315 	if (!_xMemberTD.is() && _aMemberTypeName.getLength())
316 	{
317         try
318         {
319             Reference< XTypeDescription > xMemberTD;
320             if (_xTDMgr->getByHierarchicalName( _aMemberTypeName ) >>= xMemberTD)
321             {
322                 MutexGuard aGuard( getMutex() );
323                 if (! _xMemberTD.is())
324                     _xMemberTD = xMemberTD;
325                 return _xMemberTD;
326             }
327         }
328         catch (NoSuchElementException &)
329         {
330         }
331         // never try again, if no td was found
332         _aMemberTypeName = OUString();
333     }
334 	return _xMemberTD;
335 }
336 
337 
338 //##################################################################################################
339 //##################################################################################################
340 //##################################################################################################
341 
342 void InterfaceTypeDescriptionImpl::checkInterfaceType(
343     Reference< XTypeDescription > const & type)
344 {
345     if (resolveTypedefs(type)->getTypeClass() != TypeClass_INTERFACE) {
346         throw RuntimeException(
347             OUString(
348                 RTL_CONSTASCII_USTRINGPARAM(
349                     "Interface base is not an interface type")),
350             static_cast< OWeakObject * >(this));
351     }
352 }
353 
354 namespace {
355 
356 class BaseOffset {
357 public:
358     BaseOffset(Reference< XInterfaceTypeDescription2 > const & desc);
359 
360     sal_Int32 get() const { return offset; }
361 
362 private:
363     void calculateBases(Reference< XInterfaceTypeDescription2 > const & desc);
364 
365     void calculate(Reference< XInterfaceTypeDescription2 > const & desc);
366 
367     std::set< rtl::OUString > set;
368     sal_Int32 offset;
369 };
370 
371 BaseOffset::BaseOffset(Reference< XInterfaceTypeDescription2 > const & desc) {
372     offset = 0;
373     calculateBases(desc);
374 }
375 
376 void BaseOffset::calculateBases(
377     Reference< XInterfaceTypeDescription2 > const & desc)
378 {
379     Sequence< Reference < XTypeDescription > > bases(desc->getBaseTypes());
380     for (sal_Int32 i = 0; i < bases.getLength(); ++i) {
381         calculate(
382             Reference< XInterfaceTypeDescription2 >(
383                 resolveTypedefs(bases[i]), UNO_QUERY_THROW));
384     }
385 }
386 
387 void BaseOffset::calculate(Reference< XInterfaceTypeDescription2 > const & desc)
388 {
389     if (set.insert(desc->getName()).second) {
390         calculateBases(desc);
391         offset += desc->getMembers().getLength();
392     }
393 }
394 
395 }
396 
397 //__________________________________________________________________________________________________
398 InterfaceTypeDescriptionImpl::InterfaceTypeDescriptionImpl(
399 	const Reference< XHierarchicalNameAccess > & xTDMgr,
400 	const OUString & rName, const Sequence< OUString > & rBaseTypes,
401     const Sequence< OUString > & rOptionalBaseTypes,
402 	const Sequence< sal_Int8 > & rBytes, bool published )
403 	: _xTDMgr( xTDMgr )
404 	, _aBytes( rBytes )
405 	, _aName( rName )
406 	, _aBaseTypes( rBaseTypes )
407 	, _aOptionalBaseTypes( rOptionalBaseTypes )
408 	, _membersInit( false )
409     , _published( published )
410 {
411 	g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
412 }
413 //__________________________________________________________________________________________________
414 InterfaceTypeDescriptionImpl::~InterfaceTypeDescriptionImpl()
415 {
416 	g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
417 }
418 
419 // XTypeDescription
420 //__________________________________________________________________________________________________
421 TypeClass InterfaceTypeDescriptionImpl::getTypeClass()
422 	throw(::com::sun::star::uno::RuntimeException)
423 {
424 	return TypeClass_INTERFACE;
425 }
426 //__________________________________________________________________________________________________
427 OUString InterfaceTypeDescriptionImpl::getName()
428 	throw(::com::sun::star::uno::RuntimeException)
429 {
430 	return _aName;
431 }
432 
433 // XInterfaceTypeDescription2
434 //__________________________________________________________________________________________________
435 Reference< XTypeDescription > InterfaceTypeDescriptionImpl::getBaseType()
436 	throw(::com::sun::star::uno::RuntimeException)
437 {
438     Sequence< Reference< XTypeDescription > > aBaseTypes(getBaseTypes());
439     return aBaseTypes.getLength() >= 1 ? aBaseTypes[0] : 0;
440 }
441 //__________________________________________________________________________________________________
442 Uik SAL_CALL InterfaceTypeDescriptionImpl::getUik()
443 	throw(::com::sun::star::uno::RuntimeException)
444 {
445 	return Uik();
446 }
447 //__________________________________________________________________________________________________
448 Sequence< Reference< XInterfaceMemberTypeDescription > > InterfaceTypeDescriptionImpl::getMembers()
449 	throw(::com::sun::star::uno::RuntimeException)
450 {
451     osl::MutexGuard guard(getMutex());
452     if (!_membersInit) {
453         _nBaseOffset = BaseOffset(this).get();
454         typereg::Reader reader(
455             _aBytes.getConstArray(), _aBytes.getLength(), false,
456             TYPEREG_VERSION_1);
457         sal_Int32 count = 0;
458         sal_uInt16 methodCount = reader.getMethodCount();
459         {for (sal_uInt16 i = 0; i < methodCount; ++i) {
460             RTMethodMode flags = reader.getMethodFlags(i);
461             if (flags != RT_MODE_ATTRIBUTE_GET
462                 && flags != RT_MODE_ATTRIBUTE_SET)
463             {
464                 ++count;
465             }
466         }}
467         sal_uInt16 fieldCount = reader.getFieldCount();
468         count += fieldCount;
469         _members.realloc(count);
470         sal_Int32 index = 0;
471         {for (sal_uInt16 i = 0; i < fieldCount; ++i) {
472             rtl::OUString name(reader.getFieldName(i));
473             rtl::OUStringBuffer typeName(getName());
474             typeName.appendAscii(RTL_CONSTASCII_STRINGPARAM("::"));
475             typeName.append(name);
476             RTFieldAccess flags = reader.getFieldFlags(i);
477             std::auto_ptr< stoc::registry_tdprovider::FunctionDescription >
478                 getter;
479             std::auto_ptr< stoc::registry_tdprovider::FunctionDescription >
480                 setter;
481             for (sal_uInt16 j = 0; j < methodCount; ++j) {
482                 if (reader.getMethodName(j) == name) {
483                     switch (reader.getMethodFlags(j)) {
484                     case RT_MODE_ATTRIBUTE_GET:
485                         OSL_ASSERT(getter.get() == 0);
486                         getter.reset(
487                             new stoc::registry_tdprovider::FunctionDescription(
488                                 _xTDMgr, _aBytes, j));
489                         break;
490 
491                     case RT_MODE_ATTRIBUTE_SET:
492                         OSL_ASSERT(setter.get() == 0);
493                         setter.reset(
494                             new stoc::registry_tdprovider::FunctionDescription(
495                                 _xTDMgr, _aBytes, j));
496                         break;
497 
498                     default:
499                         OSL_ASSERT(false);
500                         break;
501                     }
502                 }
503             }
504             _members[index] = new InterfaceAttributeImpl(
505                 _xTDMgr, typeName.makeStringAndClear(), name,
506                 reader.getFieldTypeName(i).replace('/', '.'),
507                 (flags & RT_ACCESS_READONLY) != 0,
508                 (flags & RT_ACCESS_BOUND) != 0, getter, setter,
509                 _nBaseOffset + index);
510             ++index;
511         }}
512         {for (sal_uInt16 i = 0; i < methodCount; ++i) {
513             RTMethodMode flags = reader.getMethodFlags(i);
514             if (flags != RT_MODE_ATTRIBUTE_GET
515                 && flags != RT_MODE_ATTRIBUTE_SET)
516             {
517                 rtl::OUString name(reader.getMethodName(i));
518                 rtl::OUStringBuffer typeName(getName());
519                 typeName.appendAscii(RTL_CONSTASCII_STRINGPARAM("::"));
520                 typeName.append(name);
521                 _members[index] = new InterfaceMethodImpl(
522                     _xTDMgr, typeName.makeStringAndClear(), name,
523                     reader.getMethodReturnTypeName(i).replace('/', '.'),
524                     _aBytes, i, flags == RT_MODE_ONEWAY, _nBaseOffset + index);
525                 ++index;
526             }
527         }}
528         _membersInit = true;
529     }
530     return _members;
531 }
532 
533 Sequence< Reference< XTypeDescription > >
534 InterfaceTypeDescriptionImpl::getBaseTypes() throw (RuntimeException) {
535     MutexGuard guard(getMutex());
536     if (_xBaseTDs.getLength() == 0 && _aBaseTypes.getLength() != 0) {
537         Sequence< Reference< XTypeDescription > > tds(_aBaseTypes.getLength());
538         for (sal_Int32 i = 0; i < _aBaseTypes.getLength(); ++i) {
539             try {
540                 _xTDMgr->getByHierarchicalName(_aBaseTypes[i]) >>= tds[i];
541             } catch (NoSuchElementException & e) {
542                 throw RuntimeException(
543                     (OUString(
544                         RTL_CONSTASCII_USTRINGPARAM(
545                             "com.sun.star.container.NoSuchElementException: "))
546                      + e.Message),
547                     static_cast< OWeakObject * >(this));
548             }
549             OSL_ASSERT(tds[i].is());
550             checkInterfaceType(tds[i]);
551         }
552         _xBaseTDs = tds;
553     }
554     return _xBaseTDs;
555 }
556 
557 Sequence< Reference< XTypeDescription > >
558 InterfaceTypeDescriptionImpl::getOptionalBaseTypes() throw (RuntimeException) {
559     MutexGuard guard(getMutex());
560     if (_xOptionalBaseTDs.getLength() == 0
561         && _aOptionalBaseTypes.getLength() != 0)
562     {
563         Sequence< Reference< XTypeDescription > > tds(
564             _aOptionalBaseTypes.getLength());
565         for (sal_Int32 i = 0; i < _aOptionalBaseTypes.getLength(); ++i) {
566             try {
567                 _xTDMgr->getByHierarchicalName(_aOptionalBaseTypes[i])
568                     >>= tds[i];
569             } catch (NoSuchElementException & e) {
570                 throw RuntimeException(
571                     (OUString(
572                         RTL_CONSTASCII_USTRINGPARAM(
573                             "com.sun.star.container.NoSuchElementException: "))
574                      + e.Message),
575                     static_cast< OWeakObject * >(this));
576             }
577             OSL_ASSERT(tds[i].is());
578             checkInterfaceType(tds[i]);
579         }
580         _xOptionalBaseTDs = tds;
581     }
582     return _xOptionalBaseTDs;
583 }
584 
585 }
586