Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : //=========================================================================
22 : // Todo:
23 : //
24 : // - closeKey() calls (according to JSC not really needed because XRegistry
25 : // implementation closes key in it's dtor.
26 : //
27 : //=========================================================================
28 : #include <osl/diagnose.h>
29 : #include <rtl/ustrbuf.hxx>
30 : #include "com/sun/star/reflection/XPublished.hpp"
31 : #include "cppuhelper/implbase1.hxx"
32 : #include "registry/reader.hxx"
33 : #include "registry/version.h"
34 : #include "base.hxx"
35 : #include "rdbtdp_tdenumeration.hxx"
36 :
37 : using namespace com::sun::star;
38 :
39 : namespace {
40 :
41 0 : class IndividualConstantTypeDescriptionImpl:
42 : public cppu::ImplInheritanceHelper1<
43 : stoc_rdbtdp::ConstantTypeDescriptionImpl,
44 : com::sun::star::reflection::XPublished >
45 : {
46 : public:
47 0 : IndividualConstantTypeDescriptionImpl(
48 : rtl::OUString const & name, com::sun::star::uno::Any const & value,
49 : bool published):
50 : cppu::ImplInheritanceHelper1<
51 : stoc_rdbtdp::ConstantTypeDescriptionImpl,
52 : com::sun::star::reflection::XPublished >(name, value),
53 0 : m_published(published) {}
54 :
55 0 : virtual sal_Bool SAL_CALL isPublished()
56 : throw (::com::sun::star::uno::RuntimeException)
57 0 : { return m_published; }
58 :
59 : private:
60 : bool m_published;
61 : };
62 :
63 : }
64 :
65 : namespace stoc_rdbtdp
66 : {
67 :
68 : //=========================================================================
69 : //=========================================================================
70 : //
71 : // TypeDescriptionEnumerationImpl Implementation.
72 : //
73 : //=========================================================================
74 : //=========================================================================
75 :
76 : // static
77 : rtl::Reference< TypeDescriptionEnumerationImpl >
78 0 : TypeDescriptionEnumerationImpl::createInstance(
79 : const uno::Reference< container::XHierarchicalNameAccess > & xTDMgr,
80 : const rtl::OUString & rModuleName,
81 : const uno::Sequence< uno::TypeClass > & rTypes,
82 : reflection::TypeDescriptionSearchDepth eDepth,
83 : const RegistryKeyList & rBaseKeys )
84 : throw ( reflection::NoSuchTypeNameException,
85 : reflection::InvalidTypeNameException,
86 : uno::RuntimeException )
87 : {
88 0 : if ( rModuleName.isEmpty() )
89 : {
90 : // Enumeration for root requested.
91 : return rtl::Reference< TypeDescriptionEnumerationImpl >(
92 : new TypeDescriptionEnumerationImpl(
93 0 : xTDMgr, rBaseKeys, rTypes, eDepth ) );
94 : }
95 :
96 0 : RegistryKeyList aModuleKeys;
97 :
98 0 : rtl::OUString aKey( rModuleName.replace( '.', '/' ) );
99 :
100 0 : bool bOpenKeySucceeded = false;
101 :
102 0 : const RegistryKeyList::const_iterator end = rBaseKeys.end();
103 0 : RegistryKeyList::const_iterator it = rBaseKeys.begin();
104 :
105 0 : while ( it != end )
106 : {
107 0 : uno::Reference< registry::XRegistryKey > xKey;
108 : try
109 : {
110 0 : xKey = (*it)->openKey( aKey );
111 0 : if ( xKey.is() )
112 : {
113 : // closes key in it's dtor (which is
114 : // called even in case of exceptions).
115 0 : RegistryKeyCloser aCloser( xKey );
116 :
117 0 : if ( xKey->isValid() )
118 : {
119 0 : bOpenKeySucceeded = true;
120 :
121 0 : if ( xKey->getValueType()
122 : == registry::RegistryValueType_BINARY )
123 : {
124 : uno::Sequence< sal_Int8 > aBytes(
125 0 : xKey->getBinaryValue() );
126 :
127 : typereg::Reader aReader(
128 0 : aBytes.getConstArray(), aBytes.getLength(), false,
129 0 : TYPEREG_VERSION_1);
130 :
131 0 : if ( aReader.getTypeClass() == RT_TYPE_MODULE )
132 : {
133 : // Do not close xKey!
134 0 : aCloser.reset();
135 :
136 0 : aModuleKeys.push_back( xKey );
137 0 : }
138 : }
139 : }
140 : else
141 : {
142 : OSL_FAIL(
143 : "TypeDescriptionEnumerationImpl::createInstance "
144 : "- Invalid registry key!" );
145 0 : }
146 : }
147 : }
148 0 : catch ( registry::InvalidRegistryException const & )
149 : {
150 : // openKey, getValueType, getBinaryValue
151 :
152 : OSL_FAIL( "TypeDescriptionEnumerationImpl::createInstance "
153 : "- Caught InvalidRegistryException!" );
154 : }
155 :
156 0 : ++it;
157 0 : }
158 :
159 0 : if ( !bOpenKeySucceeded )
160 0 : throw reflection::NoSuchTypeNameException();
161 :
162 0 : if ( aModuleKeys.empty() )
163 0 : throw reflection::InvalidTypeNameException();
164 :
165 : return rtl::Reference< TypeDescriptionEnumerationImpl >(
166 : new TypeDescriptionEnumerationImpl(
167 0 : xTDMgr, aModuleKeys, rTypes, eDepth ) );
168 : }
169 :
170 : //=========================================================================
171 0 : TypeDescriptionEnumerationImpl::TypeDescriptionEnumerationImpl(
172 : const uno::Reference< container::XHierarchicalNameAccess > & xTDMgr,
173 : const RegistryKeyList & rModuleKeys,
174 : const uno::Sequence< uno::TypeClass > & rTypes,
175 : reflection::TypeDescriptionSearchDepth eDepth )
176 : : m_aModuleKeys( rModuleKeys ),
177 : m_aTypes( rTypes ),
178 : m_eDepth( eDepth ),
179 0 : m_xTDMgr( xTDMgr )
180 : {
181 0 : g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
182 0 : }
183 :
184 : //=========================================================================
185 : // virtual
186 0 : TypeDescriptionEnumerationImpl::~TypeDescriptionEnumerationImpl()
187 : {
188 0 : RegistryKeyList::const_iterator it = m_aModuleKeys.begin();
189 0 : RegistryKeyList::const_iterator end = m_aModuleKeys.end();
190 : /*
191 : @@@ in case we enumerate root and queryMore was never called, then
192 : m_aModuleKeys contains open root keys which where passed from
193 : tdprov and must not be closed by us.
194 :
195 : while ( it != end )
196 : {
197 : try
198 : {
199 : if ( (*it)->isValid() )
200 : (*it)->closeKey();
201 : }
202 : catch (...)
203 : {
204 : // No exceptions from dtors, please!
205 : OSL_FAIL( "TypeDescriptionEnumerationImpl::~TypeDescriptionEnumerationImpl "
206 : "- Caught exception!" );
207 : }
208 :
209 : it++;
210 : }
211 : */
212 0 : it = m_aCurrentModuleSubKeys.begin();
213 0 : end = m_aCurrentModuleSubKeys.end();
214 0 : while ( it != end )
215 : {
216 : try
217 : {
218 0 : if ( (*it)->isValid() )
219 0 : (*it)->closeKey();
220 : }
221 0 : catch (Exception &)
222 : {
223 : // No exceptions from dtors, please!
224 : OSL_FAIL( "TypeDescriptionEnumerationImpl::~TypeDescriptionEnumerationImpl "
225 : "- Caught exception!" );
226 : }
227 :
228 0 : ++it;
229 : }
230 :
231 0 : g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
232 0 : }
233 :
234 : //=========================================================================
235 : //
236 : // XEnumeration (base of XTypeDescriptionEnumeration) methods
237 : //
238 : //=========================================================================
239 :
240 : // virtual
241 0 : sal_Bool SAL_CALL TypeDescriptionEnumerationImpl::hasMoreElements()
242 : throw ( uno::RuntimeException )
243 : {
244 0 : return queryMore();
245 : }
246 :
247 : //=========================================================================
248 : // virtual
249 0 : uno::Any SAL_CALL TypeDescriptionEnumerationImpl::nextElement()
250 : throw ( container::NoSuchElementException,
251 : lang::WrappedTargetException,
252 : uno::RuntimeException )
253 : {
254 0 : return uno::Any( uno::makeAny( nextTypeDescription() ) );
255 : }
256 :
257 : //=========================================================================
258 : //
259 : // XTypeDescriptionEnumeration methods
260 : //
261 : //=========================================================================
262 :
263 : // virtual
264 : uno::Reference< reflection::XTypeDescription > SAL_CALL
265 0 : TypeDescriptionEnumerationImpl::nextTypeDescription()
266 : throw ( container::NoSuchElementException,
267 : uno::RuntimeException )
268 : {
269 0 : uno::Reference< reflection::XTypeDescription > xTD( queryNext() );
270 :
271 0 : if ( xTD.is() )
272 0 : return xTD;
273 :
274 : throw container::NoSuchElementException(
275 : rtl::OUString(
276 : RTL_CONSTASCII_USTRINGPARAM("No further elements in enumeration!") ),
277 0 : static_cast< cppu::OWeakObject * >( this ) );
278 : }
279 :
280 : //=========================================================================
281 0 : bool TypeDescriptionEnumerationImpl::match(
282 : RTTypeClass eType1, uno::TypeClass eType2 )
283 : {
284 0 : switch ( eType1 )
285 : {
286 : case RT_TYPE_INTERFACE:
287 0 : return eType2 == uno::TypeClass_INTERFACE;
288 :
289 : case RT_TYPE_MODULE:
290 0 : return eType2 == uno::TypeClass_MODULE;
291 :
292 : case RT_TYPE_STRUCT:
293 0 : return eType2 == uno::TypeClass_STRUCT;
294 :
295 : case RT_TYPE_ENUM:
296 0 : return eType2 == uno::TypeClass_ENUM;
297 :
298 : case RT_TYPE_EXCEPTION:
299 0 : return eType2 == uno::TypeClass_EXCEPTION;
300 :
301 : case RT_TYPE_TYPEDEF:
302 0 : return eType2 == uno::TypeClass_TYPEDEF;
303 :
304 : case RT_TYPE_SERVICE:
305 0 : return eType2 == uno::TypeClass_SERVICE;
306 :
307 : case RT_TYPE_SINGLETON:
308 0 : return eType2 == uno::TypeClass_SINGLETON;
309 :
310 : case RT_TYPE_CONSTANTS:
311 0 : return eType2 == uno::TypeClass_CONSTANTS;
312 :
313 : case RT_TYPE_UNION:
314 0 : return eType2 == uno::TypeClass_UNION;
315 :
316 : default:
317 0 : return false;
318 : }
319 : }
320 :
321 : //=========================================================================
322 0 : bool TypeDescriptionEnumerationImpl::queryMore()
323 : {
324 0 : osl::MutexGuard aGuard( m_aMutex );
325 :
326 0 : for (;;)
327 : {
328 0 : if ( !m_aCurrentModuleSubKeys.empty() || !m_aTypeDescs.empty() )
329 : {
330 : // Okay, there is at least one more element.
331 0 : return true;
332 : }
333 :
334 0 : if ( m_aModuleKeys.empty() )
335 : {
336 : // No module keys (therefore no elements) left.
337 0 : return false;
338 : }
339 :
340 : // Note: m_aCurrentModuleSubKeys is always empty AND m_aModuleKeys is
341 : // never empty when ariving here.
342 : // ==> select new module key, fill m_aCurrentModuleSubKeys
343 :
344 0 : uno::Sequence< uno::Reference< registry::XRegistryKey > > aKeys;
345 : try
346 : {
347 0 : aKeys = m_aModuleKeys.front()->openKeys();
348 0 : for ( sal_Int32 n = 0; n < aKeys.getLength(); ++n )
349 : {
350 0 : uno::Reference< registry::XRegistryKey > xKey = aKeys[ n ];
351 :
352 : // closes key in it's dtor (which is
353 : // called even in case of exceptions).
354 0 : RegistryKeyCloser aCloser( xKey );
355 :
356 : try
357 : {
358 0 : if ( xKey->isValid() )
359 : {
360 0 : if ( xKey->getValueType()
361 : == registry::RegistryValueType_BINARY )
362 : {
363 0 : bool bIncludeIt = (m_aTypes.getLength() == 0);
364 : bool bNeedTypeClass =
365 0 : ((m_aTypes.getLength() > 0) ||
366 : (m_eDepth
367 0 : == reflection::TypeDescriptionSearchDepth_INFINITE));
368 0 : if ( bNeedTypeClass )
369 : {
370 : uno::Sequence< sal_Int8 > aBytes(
371 0 : xKey->getBinaryValue() );
372 :
373 : typereg::Reader aReader(
374 0 : aBytes.getConstArray(), aBytes.getLength(),
375 0 : false, TYPEREG_VERSION_1);
376 :
377 0 : RTTypeClass eTypeClass = aReader.getTypeClass();
378 :
379 : // Does key match requested types? Empty
380 : // sequence means include all.
381 0 : if ( m_aTypes.getLength() > 0 )
382 : {
383 0 : for ( sal_Int32 m = 0;
384 0 : m < m_aTypes.getLength();
385 : ++m )
386 : {
387 0 : if ( match(eTypeClass, m_aTypes[ m ]) )
388 : {
389 0 : bIncludeIt = true;
390 0 : break;
391 : }
392 : }
393 : }
394 :
395 0 : if ( m_eDepth ==
396 : reflection::TypeDescriptionSearchDepth_INFINITE )
397 : {
398 0 : if ( eTypeClass == RT_TYPE_MODULE )
399 : {
400 : // Do not close xKey!
401 0 : aCloser.reset();
402 :
403 : // Remember new module key.
404 0 : m_aModuleKeys.push_back( xKey );
405 : }
406 0 : }
407 : }
408 :
409 0 : if ( bIncludeIt )
410 : {
411 : // Do not close xKey!
412 0 : aCloser.reset();
413 :
414 0 : m_aCurrentModuleSubKeys.push_back( xKey );
415 : }
416 : }
417 : }
418 : else
419 : {
420 : OSL_FAIL( "TypeDescriptionEnumerationImpl::queryMore "
421 : "- Invalid registry key!" );
422 : }
423 :
424 : }
425 0 : catch ( registry::InvalidRegistryException const & )
426 : {
427 : // getValueType, getBinaryValue
428 :
429 : OSL_FAIL( "TypeDescriptionEnumerationImpl::queryMore "
430 : "- Caught InvalidRegistryException!" );
431 :
432 : // Don't stop iterating!
433 : }
434 0 : }
435 : }
436 0 : catch ( registry::InvalidRegistryException const & )
437 : {
438 : // openKeys
439 :
440 0 : for ( sal_Int32 n = 0; n < aKeys.getLength(); ++n )
441 : {
442 : try
443 : {
444 0 : aKeys[ n ]->closeKey();
445 : }
446 0 : catch ( registry::InvalidRegistryException const & )
447 : {
448 : OSL_FAIL( "TypeDescriptionEnumerationImpl::queryMore "
449 : "- Caught InvalidRegistryException!" );
450 : }
451 : }
452 : }
453 :
454 : /////////////////////////////////////////////////////////////////////
455 : // Special handling for constants contained directly in module.
456 : /////////////////////////////////////////////////////////////////////
457 :
458 : // Constants requested?
459 0 : bool bIncludeConstants = ( m_aTypes.getLength() == 0 );
460 0 : if ( !bIncludeConstants )
461 : {
462 0 : for ( sal_Int32 m = 0; m < m_aTypes.getLength(); ++m )
463 : {
464 0 : if ( m_aTypes[ m ] == uno::TypeClass_CONSTANT )
465 : {
466 0 : bIncludeConstants = true;
467 0 : break;
468 : }
469 : }
470 :
471 : }
472 :
473 0 : if ( bIncludeConstants )
474 : {
475 0 : if ( m_aModuleKeys.front()->getValueType()
476 : == registry::RegistryValueType_BINARY )
477 : {
478 : try
479 : {
480 : uno::Sequence< sal_Int8 > aBytes(
481 0 : m_aModuleKeys.front()->getBinaryValue() );
482 :
483 : typereg::Reader aReader(
484 0 : aBytes.getConstArray(), aBytes.getLength(), false,
485 0 : TYPEREG_VERSION_1);
486 :
487 0 : if ( aReader.getTypeClass() == RT_TYPE_MODULE )
488 : {
489 0 : sal_uInt16 nFields = aReader.getFieldCount();
490 0 : while ( nFields-- )
491 : {
492 : rtl::OUStringBuffer aName(
493 0 : aReader.getTypeName().replace( '/', '.' ) );
494 0 : aName.appendAscii( "." );
495 0 : aName.append( aReader.getFieldName( nFields ) );
496 :
497 : uno::Any aValue(
498 : getRTValue(
499 0 : aReader.getFieldValue( nFields ) ) );
500 :
501 : m_aTypeDescs.push_back(
502 : new IndividualConstantTypeDescriptionImpl(
503 : aName.makeStringAndClear(), aValue,
504 0 : ( ( aReader.getFieldFlags( nFields )
505 : & RT_ACCESS_PUBLISHED )
506 0 : != 0 ) ) );
507 0 : }
508 0 : }
509 : }
510 0 : catch ( registry::InvalidRegistryException const & )
511 : {
512 : // getBinaryValue
513 :
514 : OSL_FAIL( "TypeDescriptionEnumerationImpl::queryMore "
515 : "- Caught InvalidRegistryException!" );
516 : }
517 : }
518 : }
519 :
520 : /////////////////////////////////////////////////////////////////////
521 :
522 : /*
523 : @@@ m_aModuleKeys.front() may have open sub keys (may be contained in
524 : both m_aModuleKeys and m_aCurrentModuleSubKeys)!
525 :
526 : try
527 : {
528 : m_aModuleKeys.front()->closeKey();
529 : }
530 : catch ( registry::InvalidRegistryException const & )
531 : {
532 : OSL_FAIL( "TypeDescriptionEnumerationImpl::queryMore "
533 : "- Caught InvalidRegistryException!" );
534 : }
535 : */
536 : // We're done with this module key, even if there were errors.
537 0 : m_aModuleKeys.pop_front();
538 0 : }
539 :
540 : // unreachable
541 : }
542 :
543 : //=========================================================================
544 : uno::Reference< reflection::XTypeDescription >
545 0 : TypeDescriptionEnumerationImpl::queryNext()
546 : {
547 0 : osl::MutexGuard aGuard( m_aMutex );
548 :
549 0 : for (;;)
550 : {
551 0 : if ( !queryMore() )
552 0 : return uno::Reference< reflection::XTypeDescription >();
553 :
554 0 : uno::Reference< reflection::XTypeDescription > xTD;
555 :
556 0 : if ( !m_aTypeDescs.empty() )
557 : {
558 0 : xTD = m_aTypeDescs.front();
559 0 : m_aTypeDescs.pop_front();
560 0 : return xTD;
561 : }
562 :
563 : // Note: xKey is already opened.
564 : uno::Reference< registry::XRegistryKey >
565 0 : xKey( m_aCurrentModuleSubKeys.front() );
566 : /*
567 : @@@ xKey may still be contained in m_aModuleKeys, too
568 :
569 : // closes key in it's dtor (which is
570 : // called even in case of exceptions).
571 : RegistryKeyCloser aCloser( xKey );
572 : */
573 : try
574 : {
575 : {
576 0 : if ( xKey->isValid() )
577 : {
578 0 : if ( xKey->getValueType()
579 : == registry::RegistryValueType_BINARY )
580 : {
581 : uno::Sequence< sal_Int8 > aBytes(
582 0 : xKey->getBinaryValue() );
583 :
584 : xTD = createTypeDescription( aBytes,
585 : m_xTDMgr,
586 0 : false );
587 : OSL_ENSURE( xTD.is(),
588 : "TypeDescriptionEnumerationImpl::queryNext "
589 0 : "- No XTypeDescription created!" );
590 : }
591 : }
592 : else
593 : {
594 : OSL_FAIL( "TypeDescriptionEnumerationImpl::queryNext "
595 : "- Invalid registry key!" );
596 : }
597 : }
598 : }
599 0 : catch ( registry::InvalidRegistryException const & )
600 : {
601 : // getValueType, getBinaryValue
602 :
603 : OSL_FAIL( "TypeDescriptionEnumerationImpl::queryNext "
604 : "- Caught InvalidRegistryException!" );
605 : }
606 :
607 : // We're done with this key, even if there were errors.
608 0 : m_aCurrentModuleSubKeys.pop_front();
609 :
610 0 : if ( xTD.is() )
611 0 : return xTD;
612 :
613 : // next try...
614 :
615 0 : } // for (;;)
616 : }
617 :
618 : } // namespace stoc_rdbtdp
619 :
620 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|