update credits
[LibreOffice.git] / unoidl / source / legacyprovider.cxx
bloba60424a8ceb6ffef76ff9a0cea6967729c73384e
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 <cstring>
14 #include <vector>
16 #include "registry/reader.hxx"
17 #include "registry/registry.hxx"
18 #include "registry/regtype.h"
19 #include "rtl/ref.hxx"
20 #include "rtl/ustring.hxx"
21 #include "sal/types.h"
22 #include "unoidl/legacyprovider.hxx"
23 #include "unoidl/unoidl.hxx"
25 namespace unoidl {
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(static_cast< bool >(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 () {}
84 virtual rtl::Reference< Entity > getNext(OUString * name);
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 != REG_NO_ERROR) {
106 throw FileFormatException(
107 key_.getRegistryName(),
108 ("legacy format: cannot get sub-key names of " + key_.getName()
109 + ": " + OUString::number(e)));
114 rtl::Reference< Entity > Cursor::getNext(OUString * name) {
115 assert(name != 0);
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 () {}
139 virtual std::vector< OUString > getMemberNames() const;
141 virtual rtl::Reference< MapCursor > createCursor() const
142 { return new Cursor(manager_, ucr_, key_); }
144 rtl::Reference< Manager > manager_;
145 RegistryKey ucr_;
146 mutable RegistryKey key_;
149 std::vector< OUString > Module::getMemberNames() const {
150 RegistryKeyNames names;
151 RegError e = key_.getKeyNames("", names);
152 if (e != REG_NO_ERROR) {
153 throw FileFormatException(
154 key_.getRegistryName(),
155 ("legacy format: cannot get sub-key names of " + key_.getName()
156 + ": " + OUString::number(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 != 0);
167 RegValueType type;
168 sal_uInt32 size;
169 RegError e = key.getValueInfo("", &type, &size);
170 if (e != REG_NO_ERROR) {
171 throw FileFormatException(
172 key.getRegistryName(),
173 ("legacy format: cannot get value info about key " + key.getName()
174 + ": " + OUString::number(e)));
176 if (type != RG_VALUETYPE_BINARY) {
177 throw FileFormatException(
178 key.getRegistryName(),
179 ("legacy format: unexpected value type " + OUString::number(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)[0]);
192 if (e != REG_NO_ERROR) {
193 throw FileFormatException(
194 key.getRegistryName(),
195 ("legacy format: cannot get binary value of key " + key.getName()
196 + ": " + OUString::number(e)));
198 typereg::Reader reader(&(*buffer)[0], size, false, TYPEREG_VERSION_1);
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 REG_NO_ERROR:
216 break;
217 case REG_KEY_NOT_EXISTS:
218 if (probe) {
219 return rtl::Reference< Entity >();
221 // fall through
222 default:
223 throw FileFormatException(
224 key.getRegistryName(),
225 ("legacy format: cannot open sub-key " + path + " of "
226 + key.getName() + ": " + OUString::number(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.push_back(
237 AnnotatedReference(
238 reader.getSuperTypeName(j).replace('/', '.'),
239 std::vector< OUString >()));
241 std::vector< AnnotatedReference > optBases;
242 n = reader.getReferenceCount();
243 for (sal_uInt16 j = 0; j != n; ++j) {
244 optBases.push_back(
245 AnnotatedReference(
246 reader.getReferenceTypeName(j).replace('/', '.'),
247 translateAnnotations(
248 reader.getReferenceDocumentation(j))));
250 sal_uInt16 methodCount = reader.getMethodCount();
251 std::vector< InterfaceTypeEntity::Attribute > attrs;
252 n = reader.getFieldCount(); // attributes
253 for (sal_uInt16 j = 0; j != n; ++j) {
254 OUString attrName(reader.getFieldName(j));
255 std::vector< OUString > getExcs;
256 std::vector< OUString > setExcs;
257 for (sal_uInt16 k = 0; k != methodCount; ++k) {
258 if (reader.getMethodName(k) == attrName) {
259 switch (reader.getMethodFlags(k)) {
260 case RT_MODE_ATTRIBUTE_GET:
262 sal_uInt16 m
263 = reader.getMethodExceptionCount(k);
264 for (sal_uInt16 l = 0; l != m; ++l) {
265 getExcs.push_back(
266 reader.getMethodExceptionTypeName(k, l).
267 replace('/', '.'));
269 break;
271 case RT_MODE_ATTRIBUTE_SET:
273 sal_uInt16 m
274 = reader.getMethodExceptionCount(k);
275 for (sal_uInt16 l = 0; l != m; ++l) {
276 setExcs.push_back(
277 reader.getMethodExceptionTypeName(k, l).
278 replace('/', '.'));
280 break;
282 default:
283 throw FileFormatException(
284 key.getRegistryName(),
285 ("legacy format: method and attribute with same"
286 " name " + attrName
287 + " in interface type with key "
288 + sub.getName()));
292 RTFieldAccess flags = reader.getFieldFlags(j);
293 attrs.push_back(
294 InterfaceTypeEntity::Attribute(
295 attrName, reader.getFieldTypeName(j).replace('/', '.'),
296 (flags & RT_ACCESS_BOUND) != 0,
297 (flags & RT_ACCESS_READONLY) != 0, getExcs, setExcs,
298 translateAnnotations(reader.getFieldDocumentation(j))));
300 std::vector< InterfaceTypeEntity::Method > meths;
301 for (sal_uInt16 j = 0; j != methodCount; ++j) {
302 RTMethodMode flags = reader.getMethodFlags(j);
303 if (flags != RT_MODE_ATTRIBUTE_GET
304 && flags != RT_MODE_ATTRIBUTE_SET)
306 std::vector< InterfaceTypeEntity::Method::Parameter >
307 params;
308 sal_uInt16 m = reader.getMethodParameterCount(j);
309 for (sal_uInt16 k = 0; k != m; ++k) {
310 RTParamMode mode = reader.getMethodParameterFlags(j, k);
311 InterfaceTypeEntity::Method::Parameter::Direction dir;
312 switch (mode) {
313 case RT_PARAM_IN:
314 dir = InterfaceTypeEntity::Method::Parameter::DIRECTION_IN;
315 break;
316 case RT_PARAM_OUT:
317 dir = InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT;
318 break;
319 case RT_PARAM_INOUT:
320 dir = InterfaceTypeEntity::Method::Parameter::DIRECTION_IN_OUT;
321 break;
322 default:
323 throw FileFormatException(
324 key.getRegistryName(),
325 ("legacy format: unexpected mode "
326 + OUString::number(mode) + " of parameter "
327 + reader.getMethodParameterName(j, k)
328 + " of method " + reader.getMethodName(j)
329 + " in interface type with key "
330 + sub.getName()));
332 params.push_back(
333 InterfaceTypeEntity::Method::Parameter(
334 reader.getMethodParameterName(j, k),
335 (reader.getMethodParameterTypeName(j, k).
336 replace('/', '.')),
337 dir));
339 std::vector< OUString > excs;
340 m = reader.getMethodExceptionCount(j);
341 for (sal_uInt16 k = 0; k != m; ++k) {
342 excs.push_back(
343 reader.getMethodExceptionTypeName(j, k).replace(
344 '/', '.'));
346 meths.push_back(
347 InterfaceTypeEntity::Method(
348 reader.getMethodName(j),
349 reader.getMethodReturnTypeName(j).replace('/', '.'),
350 params, excs,
351 translateAnnotations(
352 reader.getMethodDocumentation(j))));
355 return new InterfaceTypeEntity(
356 reader.isPublished(), mandBases, optBases, attrs, meths,
357 translateAnnotations(reader.getDocumentation()));
359 case RT_TYPE_MODULE:
360 return new Module(manager, ucr, sub);
361 case RT_TYPE_STRUCT:
363 sal_uInt32 n = reader.getReferenceCount();
364 if (n == 0) {
365 OUString base;
366 switch (reader.getSuperTypeCount()) {
367 case 0:
368 break;
369 case 1:
370 base = reader.getSuperTypeName(0).replace('/', '.');
371 break;
372 default:
373 FileFormatException(
374 key.getRegistryName(),
375 ("legacy format: unexpected number "
376 + OUString::number(reader.getSuperTypeCount())
377 + " of super-types of plain struct type with key "
378 + sub.getName()));
380 std::vector< PlainStructTypeEntity::Member > mems;
381 n = reader.getFieldCount();
382 for (sal_uInt16 j = 0; j != n; ++j) {
383 mems.push_back(
384 PlainStructTypeEntity::Member(
385 reader.getFieldName(j),
386 reader.getFieldTypeName(j).replace('/', '.'),
387 translateAnnotations(
388 reader.getFieldDocumentation(j))));
390 return new PlainStructTypeEntity(
391 reader.isPublished(), base, mems,
392 translateAnnotations(reader.getDocumentation()));
393 } else {
394 if (reader.getSuperTypeCount() != 0) {
395 FileFormatException(
396 key.getRegistryName(),
397 ("legacy format: unexpected number "
398 + OUString::number(reader.getSuperTypeCount())
399 + " of super-types of polymorphic struct type template"
400 " with key " + sub.getName()));
402 std::vector< OUString > params;
403 for (sal_uInt16 j = 0; j != n; ++j) {
404 params.push_back(
405 reader.getReferenceTypeName(j).replace('/', '.'));
407 std::vector< PolymorphicStructTypeTemplateEntity::Member > mems;
408 n = reader.getFieldCount();
409 for (sal_uInt16 j = 0; j != n; ++j) {
410 mems.push_back(
411 PolymorphicStructTypeTemplateEntity::Member(
412 reader.getFieldName(j),
413 reader.getFieldTypeName(j).replace('/', '.'),
414 ((reader.getFieldFlags(j)
415 & RT_ACCESS_PARAMETERIZED_TYPE)
416 != 0),
417 translateAnnotations(
418 reader.getFieldDocumentation(j))));
420 return new PolymorphicStructTypeTemplateEntity(
421 reader.isPublished(), params, mems,
422 translateAnnotations(reader.getDocumentation()));
425 case RT_TYPE_ENUM:
427 std::vector< EnumTypeEntity::Member > mems;
428 sal_uInt16 n = reader.getFieldCount();
429 for (sal_uInt16 j = 0; j != n; ++j) {
430 RTConstValue v(reader.getFieldValue(j));
431 if (v.m_type != RT_TYPE_INT32) {
432 FileFormatException(
433 key.getRegistryName(),
434 ("legacy format: unexpected type "
435 + OUString::number(v.m_type) + " of value of field "
436 + reader.getFieldName(j) + " of enum type with key "
437 + sub.getName()));
439 mems.push_back(
440 EnumTypeEntity::Member(
441 reader.getFieldName(j), v.m_value.aLong,
442 translateAnnotations(reader.getFieldDocumentation(j))));
445 return new EnumTypeEntity(
446 reader.isPublished(), mems,
447 translateAnnotations(reader.getDocumentation()));
449 case RT_TYPE_EXCEPTION:
451 OUString base;
452 switch (reader.getSuperTypeCount()) {
453 case 0:
454 break;
455 case 1:
456 base = reader.getSuperTypeName(0).replace('/', '.');
457 break;
458 default:
459 throw FileFormatException(
460 key.getRegistryName(),
461 ("legacy format: unexpected number "
462 + OUString::number(reader.getSuperTypeCount())
463 + " of super-types of exception type with key "
464 + sub.getName()));
466 std::vector< ExceptionTypeEntity::Member > mems;
467 sal_uInt16 n = reader.getFieldCount();
468 for (sal_uInt16 j = 0; j != n; ++j) {
469 mems.push_back(
470 ExceptionTypeEntity::Member(
471 reader.getFieldName(j),
472 reader.getFieldTypeName(j).replace('/', '.'),
473 translateAnnotations(reader.getFieldDocumentation(j))));
475 return new ExceptionTypeEntity(
476 reader.isPublished(), base, mems,
477 translateAnnotations(reader.getDocumentation()));
479 case RT_TYPE_TYPEDEF:
480 if (reader.getSuperTypeCount() != 1) {
481 throw FileFormatException(
482 key.getRegistryName(),
483 ("legacy format: unexpected number "
484 + OUString::number(reader.getSuperTypeCount())
485 + " of super-types of typedef with key " + sub.getName()));
487 return new TypedefEntity(
488 reader.isPublished(), reader.getSuperTypeName(0).replace('/', '.'),
489 translateAnnotations(reader.getDocumentation()));
490 case RT_TYPE_SERVICE:
491 switch (reader.getSuperTypeCount()) {
492 case 0:
494 std::vector< AnnotatedReference > mandServs;
495 std::vector< AnnotatedReference > optServs;
496 std::vector< AnnotatedReference > mandIfcs;
497 std::vector< AnnotatedReference > optIfcs;
498 sal_uInt16 n = reader.getReferenceCount();
499 for (sal_uInt16 j = 0; j != n; ++j) {
500 AnnotatedReference base(
501 reader.getReferenceTypeName(j).replace('/', '.'),
502 translateAnnotations(
503 reader.getReferenceDocumentation(j)));
504 switch (reader.getReferenceSort(j)) {
505 case RT_REF_EXPORTS:
506 if ((reader.getReferenceFlags(j) & RT_ACCESS_OPTIONAL)
507 == 0)
509 mandServs.push_back(base);
510 } else {
511 optServs.push_back(base);
513 break;
514 case RT_REF_SUPPORTS:
515 if ((reader.getReferenceFlags(j) & RT_ACCESS_OPTIONAL)
516 == 0)
518 mandIfcs.push_back(base);
519 } else {
520 optIfcs.push_back(base);
522 break;
523 default:
524 throw FileFormatException(
525 key.getRegistryName(),
526 ("legacy format: unexpected mode "
527 + OUString::number(reader.getReferenceSort(j))
528 + " of reference " + reader.getReferenceTypeName(j)
529 + " in service with key " + sub.getName()));
532 std::vector< AccumulationBasedServiceEntity::Property > props;
533 n = reader.getFieldCount();
534 for (sal_uInt16 j = 0; j != n; ++j) {
535 RTFieldAccess acc = reader.getFieldFlags(j);
536 int attrs = 0;
537 if ((acc & RT_ACCESS_READONLY) != 0) {
538 attrs |= AccumulationBasedServiceEntity::Property::
539 ATTRIBUTE_READ_ONLY;
541 if ((acc & RT_ACCESS_OPTIONAL) != 0) {
542 attrs |= AccumulationBasedServiceEntity::Property::
543 ATTRIBUTE_OPTIONAL;
545 if ((acc & RT_ACCESS_MAYBEVOID) != 0) {
546 attrs |= AccumulationBasedServiceEntity::Property::
547 ATTRIBUTE_MAYBE_VOID;
549 if ((acc & RT_ACCESS_BOUND) != 0) {
550 attrs |= AccumulationBasedServiceEntity::Property::
551 ATTRIBUTE_BOUND;
553 if ((acc & RT_ACCESS_CONSTRAINED) != 0) {
554 attrs |= AccumulationBasedServiceEntity::Property::
555 ATTRIBUTE_CONSTRAINED;
557 if ((acc & RT_ACCESS_TRANSIENT) != 0) {
558 attrs |= AccumulationBasedServiceEntity::Property::
559 ATTRIBUTE_TRANSIENT;
561 if ((acc & RT_ACCESS_MAYBEAMBIGUOUS) != 0) {
562 attrs |= AccumulationBasedServiceEntity::Property::
563 ATTRIBUTE_MAYBE_AMBIGUOUS;
565 if ((acc & RT_ACCESS_MAYBEDEFAULT) != 0) {
566 attrs |= AccumulationBasedServiceEntity::Property::
567 ATTRIBUTE_MAYBE_DEFAULT;
569 if ((acc & RT_ACCESS_REMOVEABLE) != 0) {
570 attrs |= AccumulationBasedServiceEntity::Property::
571 ATTRIBUTE_REMOVABLE;
573 props.push_back(
574 AccumulationBasedServiceEntity::Property(
575 reader.getFieldName(j),
576 reader.getFieldTypeName(j).replace('/', '.'),
577 static_cast<
578 AccumulationBasedServiceEntity::Property::
579 Attributes >(attrs),
580 translateAnnotations(
581 reader.getFieldDocumentation(j))));
583 return new AccumulationBasedServiceEntity(
584 reader.isPublished(), mandServs, optServs, mandIfcs,
585 optIfcs, props,
586 translateAnnotations(reader.getDocumentation()));
588 case 1:
590 std::vector< SingleInterfaceBasedServiceEntity::Constructor >
591 ctors;
592 sal_uInt16 n = reader.getMethodCount();
593 if (n == 1 && reader.getMethodFlags(0) == RT_MODE_TWOWAY
594 && reader.getMethodName(0).isEmpty()
595 && reader.getMethodReturnTypeName(0) == "void"
596 && reader.getMethodParameterCount(0) == 0
597 && reader.getMethodExceptionCount(0) == 0)
599 ctors.push_back(
600 SingleInterfaceBasedServiceEntity::Constructor());
601 } else {
602 for (sal_uInt16 j = 0; j != n; ++j) {
603 if (reader.getMethodFlags(j) != RT_MODE_TWOWAY) {
604 throw FileFormatException(
605 key.getRegistryName(),
606 ("legacy format: unexpected mode "
607 + OUString::number(reader.getMethodFlags(j))
608 + " of constructor " + reader.getMethodName(j)
609 + " in service with key " + sub.getName()));
611 std::vector<
612 SingleInterfaceBasedServiceEntity::Constructor::
613 Parameter > params;
614 sal_uInt16 m = reader.getMethodParameterCount(j);
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.push_back(
646 SingleInterfaceBasedServiceEntity::Constructor::
647 Parameter(
648 reader.getMethodParameterName(j, k),
649 (reader.getMethodParameterTypeName(j, k).
650 replace('/', '.')),
651 (mode & RT_PARAM_REST) != 0));
653 std::vector< OUString > excs;
654 m = reader.getMethodExceptionCount(j);
655 for (sal_uInt16 k = 0; k != m; ++k) {
656 excs.push_back(
657 reader.getMethodExceptionTypeName(j, k).replace(
658 '/', '.'));
660 ctors.push_back(
661 SingleInterfaceBasedServiceEntity::Constructor(
662 reader.getMethodName(j), params, excs,
663 translateAnnotations(
664 reader.getMethodDocumentation(j))));
667 return new SingleInterfaceBasedServiceEntity(
668 reader.isPublished(),
669 reader.getSuperTypeName(0).replace('/', '.'), ctors,
670 translateAnnotations(reader.getDocumentation()));
672 default:
673 throw FileFormatException(
674 key.getRegistryName(),
675 ("legacy format: unexpected number "
676 + OUString::number(reader.getSuperTypeCount())
677 + " of super-types of service with key " + sub.getName()));
679 case RT_TYPE_SINGLETON:
681 if (reader.getSuperTypeCount() != 1) {
682 throw FileFormatException(
683 key.getRegistryName(),
684 ("legacy format: unexpected number "
685 + OUString::number(reader.getSuperTypeCount())
686 + " of super-types of singleton with key "
687 + sub.getName()));
689 OUString basePath(reader.getSuperTypeName(0));
690 OUString baseName(basePath.replace('/', '.'));
691 bool newStyle;
692 rtl::Reference< Entity > base(manager->findEntity(baseName));
693 if (base.is()) {
694 switch (base->getSort()) {
695 case Entity::SORT_INTERFACE_TYPE:
696 newStyle = true;
697 break;
698 case Entity::SORT_ACCUMULATION_BASED_SERVICE:
699 newStyle = false;
700 break;
701 default:
702 throw FileFormatException(
703 key.getRegistryName(),
704 ("legacy format: unexpected sort "
705 + OUString::number(base->getSort()) + " of base "
706 + baseName + " of singleton with key "
707 + sub.getName()));
709 } else {
710 RegistryKey key2;
711 e = ucr.openKey(basePath, key2);
712 switch (e) {
713 case REG_NO_ERROR:
714 break;
715 case REG_KEY_NOT_EXISTS:
716 throw FileFormatException(
717 key.getRegistryName(),
718 ("legacy format: unknown super-type " + basePath
719 + " of super-type with key " + sub.getName()));
720 default:
721 throw FileFormatException(
722 key.getRegistryName(),
723 ("legacy format: cannot open ucr sub-key " + basePath
724 + ": " + OUString::number(e)));
726 std::vector< char > buf2;
727 typereg::Reader reader2(getReader(key2, &buf2));
728 switch (reader2.getTypeClass()) {
729 case RT_TYPE_INTERFACE:
730 newStyle = true;
731 break;
732 case RT_TYPE_SERVICE:
733 newStyle = false;
734 break;
735 default:
736 throw FileFormatException(
737 key.getRegistryName(),
738 ("legacy format: unexpected type class "
739 + OUString::number(reader2.getTypeClass())
740 + " of super-type with key " + key2.getName()
741 + " of singleton with key " + sub.getName()));
744 return newStyle
745 ? rtl::Reference< Entity >(
746 new InterfaceBasedSingletonEntity(
747 reader.isPublished(), baseName,
748 translateAnnotations(reader.getDocumentation())))
749 : rtl::Reference< Entity >(
750 new ServiceBasedSingletonEntity(
751 reader.isPublished(), baseName,
752 translateAnnotations(reader.getDocumentation())));
754 case RT_TYPE_CONSTANTS:
756 std::vector< ConstantGroupEntity::Member > mems;
757 sal_uInt16 n = reader.getFieldCount();
758 for (sal_uInt16 j = 0; j != n; ++j) {
759 mems.push_back(
760 ConstantGroupEntity::Member(
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(
781 rtl::Reference< Manager > const & manager, OUString const & uri):
782 manager_(manager)
784 Registry reg;
785 RegError e = reg.open(uri, REG_READONLY);
786 switch (e) {
787 case REG_NO_ERROR:
788 break;
789 case REG_REGISTRY_NOT_EXISTS:
790 throw NoSuchFileException(uri);
791 default:
792 throw FileFormatException(
793 uri, "cannot open legacy file: " + OUString::number(e));
795 RegistryKey root;
796 e = reg.openRootKey(root);
797 if (e != REG_NO_ERROR) {
798 throw FileFormatException(
799 uri, "legacy format: cannot open root key: " + OUString::number(e));
801 e = root.openKey("UCR", ucr_);
802 switch (e) {
803 case REG_NO_ERROR:
804 case REG_KEY_NOT_EXISTS: // such effectively empty files exist in the wild
805 break;
806 default:
807 throw FileFormatException(
808 uri, "legacy format: cannot open UCR key: " + OUString::number(e));
812 rtl::Reference< MapCursor > LegacyProvider::createRootCursor() const {
813 return new Cursor(manager_, ucr_, ucr_);
816 rtl::Reference< Entity > LegacyProvider::findEntity(OUString const & name)
817 const
819 return ucr_.isValid()
820 ? readEntity(manager_, ucr_, ucr_, name.replace('.', '/'), true)
821 : rtl::Reference< Entity >();
824 LegacyProvider::~LegacyProvider() throw () {}
828 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */