bump product version to 6.4.0.3
[LibreOffice.git] / unoidl / source / legacyprovider.cxx
blob8e517e986f671e9015c0ba1c25b6a973dc7e90fc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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 */
10 #include <sal/config.h>
12 #include <cassert>
13 #include <vector>
15 #include <registry/reader.hxx>
16 #include <registry/registry.hxx>
17 #include <registry/regtype.h>
18 #include <rtl/ref.hxx>
19 #include <rtl/ustring.hxx>
20 #include <sal/types.h>
21 #include <unoidl/unoidl.hxx>
23 #include "legacyprovider.hxx"
25 namespace unoidl { namespace detail {
27 namespace {
29 std::vector< OUString > translateAnnotations(OUString const & documentation) {
30 std::vector< OUString > ans;
31 if (documentation.indexOf("@deprecated") != -1) {
32 //TODO: this check is somewhat crude
33 ans.push_back("deprecated");
35 return ans;
38 ConstantValue translateConstantValue(
39 RegistryKey & key, RTConstValue const & value)
41 switch (value.m_type) {
42 case RT_TYPE_BOOL:
43 return ConstantValue(value.m_value.aBool);
44 case RT_TYPE_BYTE:
45 return ConstantValue(value.m_value.aByte);
46 case RT_TYPE_INT16:
47 return ConstantValue(value.m_value.aShort);
48 case RT_TYPE_UINT16:
49 return ConstantValue(value.m_value.aUShort);
50 case RT_TYPE_INT32:
51 return ConstantValue(value.m_value.aLong);
52 case RT_TYPE_UINT32:
53 return ConstantValue(value.m_value.aULong);
54 case RT_TYPE_INT64:
55 return ConstantValue(value.m_value.aHyper);
56 case RT_TYPE_UINT64:
57 return ConstantValue(value.m_value.aUHyper);
58 case RT_TYPE_FLOAT:
59 return ConstantValue(value.m_value.aFloat);
60 case RT_TYPE_DOUBLE:
61 return ConstantValue(value.m_value.aDouble);
62 default:
63 throw FileFormatException(
64 key.getRegistryName(),
65 ("legacy format: unexpected type " + OUString::number(value.m_type)
66 + " of value of a field of constant group with key "
67 + key.getName()));
71 rtl::Reference< Entity > readEntity(
72 rtl::Reference< Manager > const & manager, RegistryKey & ucr,
73 RegistryKey & key, OUString const & path, bool probe);
75 class Cursor: public MapCursor {
76 public:
77 Cursor(
78 rtl::Reference< Manager > const & manager, RegistryKey const & ucr,
79 RegistryKey const & key);
81 private:
82 virtual ~Cursor() throw () override {}
84 virtual rtl::Reference< Entity > getNext(OUString * name) override;
86 rtl::Reference< Manager > manager_;
87 RegistryKey ucr_;
88 RegistryKey key_;
89 OUString prefix_;
90 RegistryKeyNames names_;
91 sal_uInt32 index_;
94 Cursor::Cursor(
95 rtl::Reference< Manager > const & manager, RegistryKey const & ucr,
96 RegistryKey const & key):
97 manager_(manager), ucr_(ucr), key_(key), index_(0)
99 if (ucr_.isValid()) {
100 prefix_ = key_.getName();
101 if (!prefix_.endsWith("/")) {
102 prefix_ += "/";
104 RegError e = key_.getKeyNames("", names_);
105 if (e != RegError::NO_ERROR) {
106 throw FileFormatException(
107 key_.getRegistryName(),
108 ("legacy format: cannot get sub-key names of " + key_.getName()
109 + ": " + OUString::number(static_cast<int>(e))));
114 rtl::Reference< Entity > Cursor::getNext(OUString * name) {
115 assert(name != nullptr);
116 rtl::Reference< Entity > ent;
117 if (index_ != names_.getLength()) {
118 OUString path(names_.getElement(index_));
119 assert(path.match(prefix_));
120 *name = path.copy(prefix_.getLength());
121 ent = readEntity(manager_, ucr_, key_, *name, false);
122 assert(ent.is());
123 ++index_;
125 return ent;
128 class Module: public ModuleEntity {
129 public:
130 Module(
131 rtl::Reference< Manager > const & manager, RegistryKey const & ucr,
132 RegistryKey const & key):
133 manager_(manager), ucr_(ucr), key_(key)
136 private:
137 virtual ~Module() throw () override {}
139 virtual std::vector< OUString > getMemberNames() const override;
141 virtual rtl::Reference< MapCursor > createCursor() const override
142 { return new Cursor(manager_, ucr_, key_); }
144 rtl::Reference< Manager > manager_;
145 RegistryKey const ucr_;
146 mutable RegistryKey key_;
149 std::vector< OUString > Module::getMemberNames() const {
150 RegistryKeyNames names;
151 RegError e = key_.getKeyNames("", names);
152 if (e != RegError::NO_ERROR) {
153 throw FileFormatException(
154 key_.getRegistryName(),
155 ("legacy format: cannot get sub-key names of " + key_.getName()
156 + ": " + OUString::number(static_cast<int>(e))));
158 std::vector< OUString > ns;
159 for (sal_uInt32 i = 0; i != names.getLength(); ++i) {
160 ns.push_back(names.getElement(i));
162 return ns;
165 typereg::Reader getReader(RegistryKey & key, std::vector< char > * buffer) {
166 assert(buffer != nullptr);
167 RegValueType type;
168 sal_uInt32 size;
169 RegError e = key.getValueInfo("", &type, &size);
170 if (e != RegError::NO_ERROR) {
171 throw FileFormatException(
172 key.getRegistryName(),
173 ("legacy format: cannot get value info about key " + key.getName()
174 + ": " + OUString::number(static_cast<int>(e))));
176 if (type != RegValueType::BINARY) {
177 throw FileFormatException(
178 key.getRegistryName(),
179 ("legacy format: unexpected value type " + OUString::number(static_cast<int>(type))
180 + " of key " + key.getName()));
182 if (size == 0
183 /*TODO: || size > std::numeric_limits< std::vector< char >::size_type >::max() */)
185 throw FileFormatException(
186 key.getRegistryName(),
187 ("legacy format: bad binary value size " + OUString::number(size)
188 + " of key " + key.getName()));
190 buffer->resize(static_cast< std::vector< char >::size_type >(size));
191 e = key.getValue("", buffer->data());
192 if (e != RegError::NO_ERROR) {
193 throw FileFormatException(
194 key.getRegistryName(),
195 ("legacy format: cannot get binary value of key " + key.getName()
196 + ": " + OUString::number(static_cast<int>(e))));
198 typereg::Reader reader(buffer->data(), size);
199 if (!reader.isValid()) {
200 throw FileFormatException(
201 key.getRegistryName(),
202 "legacy format: malformed binary value of key " + key.getName());
204 return reader;
207 rtl::Reference< Entity > readEntity(
208 rtl::Reference< Manager > const & manager, RegistryKey & ucr,
209 RegistryKey & key, OUString const & path, bool probe)
211 assert(manager.is());
212 RegistryKey sub;
213 RegError e = key.openKey(path, sub);
214 switch (e) {
215 case RegError::NO_ERROR:
216 break;
217 case RegError::KEY_NOT_EXISTS:
218 if (probe) {
219 return rtl::Reference< Entity >();
221 [[fallthrough]];
222 default:
223 throw FileFormatException(
224 key.getRegistryName(),
225 ("legacy format: cannot open sub-key " + path + " of "
226 + key.getName() + ": " + OUString::number(static_cast<int>(e))));
228 std::vector< char > buf;
229 typereg::Reader reader(getReader(sub, &buf));
230 switch (reader.getTypeClass()) {
231 case RT_TYPE_INTERFACE:
233 std::vector< AnnotatedReference > mandBases;
234 sal_uInt16 n = reader.getSuperTypeCount();
235 for (sal_uInt16 j = 0; j != n; ++j) {
236 mandBases.emplace_back(
237 reader.getSuperTypeName(j).replace('/', '.'),
238 std::vector< OUString >());
240 std::vector< AnnotatedReference > optBases;
241 n = reader.getReferenceCount();
242 for (sal_uInt16 j = 0; j != n; ++j) {
243 optBases.emplace_back(
244 reader.getReferenceTypeName(j).replace('/', '.'),
245 translateAnnotations(reader.getReferenceDocumentation(j)));
247 sal_uInt16 methodCount = reader.getMethodCount();
248 std::vector< InterfaceTypeEntity::Attribute > attrs;
249 n = reader.getFieldCount(); // attributes
250 for (sal_uInt16 j = 0; j != n; ++j) {
251 OUString attrName(reader.getFieldName(j));
252 std::vector< OUString > getExcs;
253 std::vector< OUString > setExcs;
254 for (sal_uInt16 k = 0; k != methodCount; ++k) {
255 if (reader.getMethodName(k) == attrName) {
256 switch (reader.getMethodFlags(k)) {
257 case RTMethodMode::ATTRIBUTE_GET:
259 sal_uInt16 m
260 = reader.getMethodExceptionCount(k);
261 // cid#1213376 unhelpfully warns about an
262 // untrusted loop bound here:
263 // coverity[tainted_data] - trusted data source
264 for (sal_uInt16 l = 0; l != m; ++l) {
265 getExcs.push_back(
266 reader.getMethodExceptionTypeName(k, l).
267 replace('/', '.'));
269 break;
271 case RTMethodMode::ATTRIBUTE_SET:
273 sal_uInt16 m
274 = reader.getMethodExceptionCount(k);
275 // cid#1213376 unhelpfully warns about an
276 // untrusted loop bound here:
277 // coverity[tainted_data] - trusted data source
278 for (sal_uInt16 l = 0; l != m; ++l) {
279 setExcs.push_back(
280 reader.getMethodExceptionTypeName(k, l).
281 replace('/', '.'));
283 break;
285 default:
286 throw FileFormatException(
287 key.getRegistryName(),
288 ("legacy format: method and attribute with same"
289 " name " + attrName
290 + " in interface type with key "
291 + sub.getName()));
295 RTFieldAccess flags = reader.getFieldFlags(j);
296 attrs.emplace_back(
297 attrName, reader.getFieldTypeName(j).replace('/', '.'),
298 bool(flags & RTFieldAccess::BOUND),
299 bool(flags & RTFieldAccess::READONLY), getExcs, setExcs,
300 translateAnnotations(reader.getFieldDocumentation(j)));
302 std::vector< InterfaceTypeEntity::Method > meths;
303 meths.reserve(methodCount);
304 for (sal_uInt16 j = 0; j != methodCount; ++j) {
305 RTMethodMode flags = reader.getMethodFlags(j);
306 if (flags != RTMethodMode::ATTRIBUTE_GET
307 && flags != RTMethodMode::ATTRIBUTE_SET)
309 std::vector< InterfaceTypeEntity::Method::Parameter >
310 params;
311 sal_uInt16 m = reader.getMethodParameterCount(j);
312 // cid#1213376 unhelpfully warns about an untrusted loop
313 // bound here:
314 // coverity[tainted_data] - trusted data source
315 for (sal_uInt16 k = 0; k != m; ++k) {
316 RTParamMode mode = reader.getMethodParameterFlags(j, k);
317 InterfaceTypeEntity::Method::Parameter::Direction dir;
318 switch (mode) {
319 case RT_PARAM_IN:
320 dir = InterfaceTypeEntity::Method::Parameter::DIRECTION_IN;
321 break;
322 case RT_PARAM_OUT:
323 dir = InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT;
324 break;
325 case RT_PARAM_INOUT:
326 dir = InterfaceTypeEntity::Method::Parameter::DIRECTION_IN_OUT;
327 break;
328 default:
329 throw FileFormatException(
330 key.getRegistryName(),
331 ("legacy format: unexpected mode "
332 + OUString::number(mode) + " of parameter "
333 + reader.getMethodParameterName(j, k)
334 + " of method " + reader.getMethodName(j)
335 + " in interface type with key "
336 + sub.getName()));
338 params.emplace_back(
339 reader.getMethodParameterName(j, k),
340 (reader.getMethodParameterTypeName(j, k).
341 replace('/', '.')),
342 dir);
344 std::vector< OUString > excs;
345 m = reader.getMethodExceptionCount(j);
346 // cid#1213376 unhelpfully warns about an untrusted loop
347 // bound here:
348 // coverity[tainted_data] - trusted data source
349 for (sal_uInt16 k = 0; k != m; ++k) {
350 excs.push_back(
351 reader.getMethodExceptionTypeName(j, k).replace(
352 '/', '.'));
354 meths.emplace_back(
355 reader.getMethodName(j),
356 reader.getMethodReturnTypeName(j).replace('/', '.'),
357 params, excs,
358 translateAnnotations(
359 reader.getMethodDocumentation(j)));
362 return new InterfaceTypeEntity(
363 reader.isPublished(), mandBases, optBases, attrs, meths,
364 translateAnnotations(reader.getDocumentation()));
366 case RT_TYPE_MODULE:
367 return new Module(manager, ucr, sub);
368 case RT_TYPE_STRUCT:
370 sal_uInt16 n = reader.getReferenceCount();
371 if (n == 0) {
372 OUString base;
373 switch (reader.getSuperTypeCount()) {
374 case 0:
375 break;
376 case 1:
377 base = reader.getSuperTypeName(0).replace('/', '.');
378 break;
379 default:
380 throw FileFormatException(
381 key.getRegistryName(),
382 ("legacy format: unexpected number "
383 + OUString::number(reader.getSuperTypeCount())
384 + " of super-types of plain struct type with key "
385 + sub.getName()));
387 std::vector< PlainStructTypeEntity::Member > mems;
388 n = reader.getFieldCount();
389 for (sal_uInt16 j = 0; j != n; ++j) {
390 mems.emplace_back(
391 reader.getFieldName(j),
392 reader.getFieldTypeName(j).replace('/', '.'),
393 translateAnnotations(reader.getFieldDocumentation(j)));
395 return new PlainStructTypeEntity(
396 reader.isPublished(), base, mems,
397 translateAnnotations(reader.getDocumentation()));
398 } else {
399 if (reader.getSuperTypeCount() != 0) {
400 throw FileFormatException(
401 key.getRegistryName(),
402 ("legacy format: unexpected number "
403 + OUString::number(reader.getSuperTypeCount())
404 + " of super-types of polymorphic struct type template"
405 " with key " + sub.getName()));
407 std::vector< OUString > params;
408 for (sal_uInt16 j = 0; j != n; ++j) {
409 params.push_back(
410 reader.getReferenceTypeName(j).replace('/', '.'));
412 std::vector< PolymorphicStructTypeTemplateEntity::Member > mems;
413 n = reader.getFieldCount();
414 for (sal_uInt16 j = 0; j != n; ++j) {
415 mems.emplace_back(
416 reader.getFieldName(j),
417 reader.getFieldTypeName(j).replace('/', '.'),
418 bool(
419 reader.getFieldFlags(j)
420 & RTFieldAccess::PARAMETERIZED_TYPE),
421 translateAnnotations(reader.getFieldDocumentation(j)));
423 return new PolymorphicStructTypeTemplateEntity(
424 reader.isPublished(), params, mems,
425 translateAnnotations(reader.getDocumentation()));
428 case RT_TYPE_ENUM:
430 std::vector< EnumTypeEntity::Member > mems;
431 sal_uInt16 n = reader.getFieldCount();
432 for (sal_uInt16 j = 0; j != n; ++j) {
433 RTConstValue v(reader.getFieldValue(j));
434 if (v.m_type != RT_TYPE_INT32) {
435 throw FileFormatException(
436 key.getRegistryName(),
437 ("legacy format: unexpected type "
438 + OUString::number(v.m_type) + " of value of field "
439 + reader.getFieldName(j) + " of enum type with key "
440 + sub.getName()));
442 mems.emplace_back(
443 reader.getFieldName(j), v.m_value.aLong,
444 translateAnnotations(reader.getFieldDocumentation(j)));
447 return new EnumTypeEntity(
448 reader.isPublished(), mems,
449 translateAnnotations(reader.getDocumentation()));
451 case RT_TYPE_EXCEPTION:
453 OUString base;
454 switch (reader.getSuperTypeCount()) {
455 case 0:
456 break;
457 case 1:
458 base = reader.getSuperTypeName(0).replace('/', '.');
459 break;
460 default:
461 throw FileFormatException(
462 key.getRegistryName(),
463 ("legacy format: unexpected number "
464 + OUString::number(reader.getSuperTypeCount())
465 + " of super-types of exception type with key "
466 + sub.getName()));
468 std::vector< ExceptionTypeEntity::Member > mems;
469 sal_uInt16 n = reader.getFieldCount();
470 for (sal_uInt16 j = 0; j != n; ++j) {
471 mems.emplace_back(
472 reader.getFieldName(j),
473 reader.getFieldTypeName(j).replace('/', '.'),
474 translateAnnotations(reader.getFieldDocumentation(j)));
476 return new ExceptionTypeEntity(
477 reader.isPublished(), base, mems,
478 translateAnnotations(reader.getDocumentation()));
480 case RT_TYPE_TYPEDEF:
481 if (reader.getSuperTypeCount() != 1) {
482 throw FileFormatException(
483 key.getRegistryName(),
484 ("legacy format: unexpected number "
485 + OUString::number(reader.getSuperTypeCount())
486 + " of super-types of typedef with key " + sub.getName()));
488 return new TypedefEntity(
489 reader.isPublished(), reader.getSuperTypeName(0).replace('/', '.'),
490 translateAnnotations(reader.getDocumentation()));
491 case RT_TYPE_SERVICE:
492 switch (reader.getSuperTypeCount()) {
493 case 0:
495 std::vector< AnnotatedReference > mandServs;
496 std::vector< AnnotatedReference > optServs;
497 std::vector< AnnotatedReference > mandIfcs;
498 std::vector< AnnotatedReference > optIfcs;
499 sal_uInt16 n = reader.getReferenceCount();
500 for (sal_uInt16 j = 0; j != n; ++j) {
501 AnnotatedReference base{
502 reader.getReferenceTypeName(j).replace('/', '.'),
503 translateAnnotations(
504 reader.getReferenceDocumentation(j))};
505 switch (reader.getReferenceSort(j)) {
506 case RTReferenceType::EXPORTS:
507 if (!(reader.getReferenceFlags(j) & RTFieldAccess::OPTIONAL))
509 mandServs.push_back(base);
510 } else {
511 optServs.push_back(base);
513 break;
514 case RTReferenceType::SUPPORTS:
515 if (!(reader.getReferenceFlags(j) & RTFieldAccess::OPTIONAL))
517 mandIfcs.push_back(base);
518 } else {
519 optIfcs.push_back(base);
521 break;
522 default:
523 throw FileFormatException(
524 key.getRegistryName(),
525 ("legacy format: unexpected mode "
526 + OUString::number(static_cast<int>(reader.getReferenceSort(j)))
527 + " of reference " + reader.getReferenceTypeName(j)
528 + " in service with key " + sub.getName()));
531 std::vector< AccumulationBasedServiceEntity::Property > props;
532 n = reader.getFieldCount();
533 for (sal_uInt16 j = 0; j != n; ++j) {
534 RTFieldAccess acc = reader.getFieldFlags(j);
535 int attrs = 0;
536 if (acc & RTFieldAccess::READONLY) {
537 attrs |= AccumulationBasedServiceEntity::Property::
538 ATTRIBUTE_READ_ONLY;
540 if (acc & RTFieldAccess::OPTIONAL) {
541 attrs |= AccumulationBasedServiceEntity::Property::
542 ATTRIBUTE_OPTIONAL;
544 if (acc & RTFieldAccess::MAYBEVOID) {
545 attrs |= AccumulationBasedServiceEntity::Property::
546 ATTRIBUTE_MAYBE_VOID;
548 if (acc & RTFieldAccess::BOUND) {
549 attrs |= AccumulationBasedServiceEntity::Property::
550 ATTRIBUTE_BOUND;
552 if (acc & RTFieldAccess::CONSTRAINED) {
553 attrs |= AccumulationBasedServiceEntity::Property::
554 ATTRIBUTE_CONSTRAINED;
556 if (acc & RTFieldAccess::TRANSIENT) {
557 attrs |= AccumulationBasedServiceEntity::Property::
558 ATTRIBUTE_TRANSIENT;
560 if (acc & RTFieldAccess::MAYBEAMBIGUOUS) {
561 attrs |= AccumulationBasedServiceEntity::Property::
562 ATTRIBUTE_MAYBE_AMBIGUOUS;
564 if (acc & RTFieldAccess::MAYBEDEFAULT) {
565 attrs |= AccumulationBasedServiceEntity::Property::
566 ATTRIBUTE_MAYBE_DEFAULT;
568 if (acc & RTFieldAccess::REMOVABLE) {
569 attrs |= AccumulationBasedServiceEntity::Property::
570 ATTRIBUTE_REMOVABLE;
572 props.emplace_back(
573 reader.getFieldName(j),
574 reader.getFieldTypeName(j).replace('/', '.'),
575 static_cast<
576 AccumulationBasedServiceEntity::Property::
577 Attributes >(attrs),
578 translateAnnotations(reader.getFieldDocumentation(j)));
580 return new AccumulationBasedServiceEntity(
581 reader.isPublished(), mandServs, optServs, mandIfcs,
582 optIfcs, props,
583 translateAnnotations(reader.getDocumentation()));
585 case 1:
587 std::vector< SingleInterfaceBasedServiceEntity::Constructor >
588 ctors;
589 sal_uInt16 n = reader.getMethodCount();
590 if (n == 1 && reader.getMethodFlags(0) == RTMethodMode::TWOWAY
591 && reader.getMethodName(0).isEmpty()
592 && reader.getMethodReturnTypeName(0) == "void"
593 && reader.getMethodParameterCount(0) == 0
594 && reader.getMethodExceptionCount(0) == 0)
596 ctors.push_back(
597 SingleInterfaceBasedServiceEntity::Constructor());
598 } else {
599 for (sal_uInt16 j = 0; j != n; ++j) {
600 if (reader.getMethodFlags(j) != RTMethodMode::TWOWAY) {
601 throw FileFormatException(
602 key.getRegistryName(),
603 ("legacy format: unexpected mode "
604 + OUString::number(static_cast<int>(reader.getMethodFlags(j)))
605 + " of constructor " + reader.getMethodName(j)
606 + " in service with key " + sub.getName()));
608 std::vector<
609 SingleInterfaceBasedServiceEntity::Constructor::
610 Parameter > params;
611 sal_uInt16 m = reader.getMethodParameterCount(j);
612 // cid#1213376 unhelpfully warns about an untrusted
613 // loop bound here:
614 // coverity[tainted_data] - trusted data source
615 for (sal_uInt16 k = 0; k != m; ++k) {
616 RTParamMode mode
617 = reader.getMethodParameterFlags(j, k);
618 if ((mode & ~RT_PARAM_REST) != RT_PARAM_IN) {
619 throw FileFormatException(
620 key.getRegistryName(),
621 ("legacy format: unexpected mode "
622 + OUString::number(mode)
623 + " of parameter "
624 + reader.getMethodParameterName(j, k)
625 + " of constructor "
626 + reader.getMethodName(j)
627 + " in service with key "
628 + sub.getName()));
630 if ((mode & RT_PARAM_REST) != 0
631 && !(m == 1
632 && ((reader.getMethodParameterTypeName(
633 j, 0))
634 == "any")))
636 throw FileFormatException(
637 key.getRegistryName(),
638 ("legacy format: bad rest parameter "
639 + reader.getMethodParameterName(j, k)
640 + " of constructor "
641 + reader.getMethodName(j)
642 + " in service with key "
643 + sub.getName()));
645 params.emplace_back(
646 reader.getMethodParameterName(j, k),
647 (reader.getMethodParameterTypeName(j, k).
648 replace('/', '.')),
649 (mode & RT_PARAM_REST) != 0);
651 std::vector< OUString > excs;
652 m = reader.getMethodExceptionCount(j);
653 // cid#1213376 unhelpfully warns about an untrusted
654 // loop bound here:
655 // coverity[tainted_data] - trusted data source
656 for (sal_uInt16 k = 0; k != m; ++k) {
657 excs.push_back(
658 reader.getMethodExceptionTypeName(j, k).replace(
659 '/', '.'));
661 ctors.push_back(
662 SingleInterfaceBasedServiceEntity::Constructor(
663 reader.getMethodName(j), params, excs,
664 translateAnnotations(
665 reader.getMethodDocumentation(j))));
668 return new SingleInterfaceBasedServiceEntity(
669 reader.isPublished(),
670 reader.getSuperTypeName(0).replace('/', '.'), ctors,
671 translateAnnotations(reader.getDocumentation()));
673 default:
674 throw FileFormatException(
675 key.getRegistryName(),
676 ("legacy format: unexpected number "
677 + OUString::number(reader.getSuperTypeCount())
678 + " of super-types of service with key " + sub.getName()));
680 case RT_TYPE_SINGLETON:
682 if (reader.getSuperTypeCount() != 1) {
683 throw FileFormatException(
684 key.getRegistryName(),
685 ("legacy format: unexpected number "
686 + OUString::number(reader.getSuperTypeCount())
687 + " of super-types of singleton with key "
688 + sub.getName()));
690 OUString basePath(reader.getSuperTypeName(0));
691 OUString baseName(basePath.replace('/', '.'));
692 bool newStyle;
693 rtl::Reference< Entity > base(manager->findEntity(baseName));
694 if (base.is()) {
695 switch (base->getSort()) {
696 case Entity::SORT_INTERFACE_TYPE:
697 newStyle = true;
698 break;
699 case Entity::SORT_ACCUMULATION_BASED_SERVICE:
700 newStyle = false;
701 break;
702 default:
703 throw FileFormatException(
704 key.getRegistryName(),
705 ("legacy format: unexpected sort "
706 + OUString::number(base->getSort()) + " of base "
707 + baseName + " of singleton with key "
708 + sub.getName()));
710 } else {
711 RegistryKey key2;
712 e = ucr.openKey(basePath, key2);
713 switch (e) {
714 case RegError::NO_ERROR:
715 break;
716 case RegError::KEY_NOT_EXISTS:
717 throw FileFormatException(
718 key.getRegistryName(),
719 ("legacy format: unknown super-type " + basePath
720 + " of super-type with key " + sub.getName()));
721 default:
722 throw FileFormatException(
723 key.getRegistryName(),
724 ("legacy format: cannot open ucr sub-key " + basePath
725 + ": " + OUString::number(static_cast<int>(e))));
727 std::vector< char > buf2;
728 typereg::Reader reader2(getReader(key2, &buf2));
729 switch (reader2.getTypeClass()) {
730 case RT_TYPE_INTERFACE:
731 newStyle = true;
732 break;
733 case RT_TYPE_SERVICE:
734 newStyle = false;
735 break;
736 default:
737 throw FileFormatException(
738 key.getRegistryName(),
739 ("legacy format: unexpected type class "
740 + OUString::number(reader2.getTypeClass())
741 + " of super-type with key " + key2.getName()
742 + " of singleton with key " + sub.getName()));
745 return newStyle
746 ? rtl::Reference< Entity >(
747 new InterfaceBasedSingletonEntity(
748 reader.isPublished(), baseName,
749 translateAnnotations(reader.getDocumentation())))
750 : rtl::Reference< Entity >(
751 new ServiceBasedSingletonEntity(
752 reader.isPublished(), baseName,
753 translateAnnotations(reader.getDocumentation())));
755 case RT_TYPE_CONSTANTS:
757 std::vector< ConstantGroupEntity::Member > mems;
758 sal_uInt16 n = reader.getFieldCount();
759 for (sal_uInt16 j = 0; j != n; ++j) {
760 mems.emplace_back(
761 reader.getFieldName(j),
762 translateConstantValue(sub, reader.getFieldValue(j)),
763 translateAnnotations(reader.getFieldDocumentation(j)));
765 return new ConstantGroupEntity(
766 reader.isPublished(), mems,
767 translateAnnotations(reader.getDocumentation()));
769 default:
770 throw FileFormatException(
771 key.getRegistryName(),
772 ("legacy format: unexpected type class "
773 + OUString::number(reader.getTypeClass()) + " of key "
774 + sub.getName()));
780 LegacyProvider::LegacyProvider(Manager & manager, OUString const & uri):
781 manager_(manager)
783 Registry reg;
784 RegError e = reg.open(uri, RegAccessMode::READONLY);
785 switch (e) {
786 case RegError::NO_ERROR:
787 break;
788 case RegError::REGISTRY_NOT_EXISTS:
789 throw NoSuchFileException(uri);
790 default:
791 throw FileFormatException(
792 uri, "cannot open legacy file: " + OUString::number(static_cast<int>(e)));
794 RegistryKey root;
795 e = reg.openRootKey(root);
796 if (e != RegError::NO_ERROR) {
797 throw FileFormatException(
798 uri, "legacy format: cannot open root key: " + OUString::number(static_cast<int>(e)));
800 e = root.openKey("UCR", ucr_);
801 switch (e) {
802 case RegError::NO_ERROR:
803 case RegError::KEY_NOT_EXISTS: // such effectively empty files exist in the wild
804 break;
805 default:
806 throw FileFormatException(
807 uri, "legacy format: cannot open UCR key: " + OUString::number(static_cast<int>(e)));
811 rtl::Reference< MapCursor > LegacyProvider::createRootCursor() const {
812 return new Cursor(&manager_, ucr_, ucr_);
815 rtl::Reference< Entity > LegacyProvider::findEntity(OUString const & name)
816 const
818 return ucr_.isValid()
819 ? readEntity(&manager_, ucr_, ucr_, name.replace('.', '/'), true)
820 : rtl::Reference< Entity >();
823 LegacyProvider::~LegacyProvider() throw () {}
827 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */