bump product version to 5.0.4.1
[LibreOffice.git] / unoidl / source / unoidl.cxx
blobe5573f0b124bd4db76ca89578d3cb2120ea97381
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 <set>
13 #include <vector>
15 #include "osl/file.h"
16 #include "osl/file.hxx"
17 #include "osl/mutex.hxx"
18 #include "rtl/ref.hxx"
19 #include "rtl/ustring.hxx"
20 #include "unoidl/unoidl.hxx"
22 #include "legacyprovider.hxx"
23 #include "sourcefileprovider.hxx"
24 #include "sourcetreeprovider.hxx"
25 #include "unoidlprovider.hxx"
27 namespace unoidl {
29 namespace {
31 class AggregatingModule: public ModuleEntity {
32 public:
33 AggregatingModule(
34 std::vector< rtl::Reference< Provider > > const & providers,
35 OUString const & name):
36 providers_(providers), name_(name)
39 private:
40 virtual ~AggregatingModule() throw () {}
42 virtual std::vector< OUString > getMemberNames() const SAL_OVERRIDE;
44 virtual rtl::Reference< MapCursor > createCursor() const SAL_OVERRIDE;
46 std::vector< rtl::Reference< Provider > > providers_;
47 OUString name_;
50 std::vector< OUString > AggregatingModule::getMemberNames() const {
51 std::set< OUString > names;
52 for (std::vector< rtl::Reference< Provider > >::const_iterator i(
53 providers_.begin());
54 i != providers_.end(); ++i)
56 rtl::Reference< Entity > ent((*i)->findEntity(name_));
57 if (ent.is() && ent->getSort() == Entity::SORT_MODULE) {
58 std::vector< OUString > ns(
59 static_cast< ModuleEntity * >(ent.get())->getMemberNames());
60 names.insert(ns.begin(), ns.end());
63 return std::vector< OUString >(names.begin(), names.end());
66 class AggregatingCursor: public MapCursor {
67 public:
68 AggregatingCursor(
69 std::vector< rtl::Reference< Provider > > const & providers,
70 OUString const & name):
71 providers_(providers), name_(name), iterator_(providers_.begin())
72 { findCursor(); }
74 private:
75 virtual ~AggregatingCursor() throw () {}
77 virtual rtl::Reference< Entity > getNext(OUString * name) SAL_OVERRIDE;
79 void findCursor();
81 std::vector< rtl::Reference< Provider > > providers_;
82 OUString name_;
83 std::vector< rtl::Reference< Provider > >::iterator iterator_;
84 rtl::Reference< MapCursor > cursor_;
85 std::set< OUString > seen_;
88 rtl::Reference< Entity > AggregatingCursor::getNext(OUString * name) {
89 while (cursor_.is()) {
90 OUString n;
91 rtl::Reference< Entity > ent(cursor_->getNext(&n));
92 if (ent.is()) {
93 if (seen_.insert(n).second) {
94 if (name != 0) {
95 *name = n;
97 return ent->getSort() == Entity::SORT_MODULE
98 ? new AggregatingModule(
99 providers_, (name_.isEmpty() ? name_ : name_ + ".") + n)
100 : ent;
102 } else {
103 cursor_.clear();
104 findCursor();
107 return rtl::Reference< Entity >();
110 void AggregatingCursor::findCursor() {
111 for (; !cursor_.is() && iterator_ != providers_.end(); ++iterator_) {
112 if (name_.isEmpty()) {
113 cursor_ = (*iterator_)->createRootCursor();
114 } else {
115 rtl::Reference< Entity > ent((*iterator_)->findEntity(name_));
116 if (ent.is() && ent->getSort() == Entity::SORT_MODULE) {
117 cursor_ = static_cast< ModuleEntity * >(ent.get())->
118 createCursor();
124 rtl::Reference< MapCursor > AggregatingModule::createCursor() const {
125 return new AggregatingCursor(providers_, name_);
130 NoSuchFileException::~NoSuchFileException() throw () {}
132 FileFormatException::~FileFormatException() throw () {}
134 Entity::~Entity() throw () {}
136 MapCursor::~MapCursor() throw () {}
138 ModuleEntity::~ModuleEntity() throw () {}
140 PublishableEntity::~PublishableEntity() throw () {}
142 EnumTypeEntity::~EnumTypeEntity() throw () {}
144 PlainStructTypeEntity::~PlainStructTypeEntity() throw () {}
146 PolymorphicStructTypeTemplateEntity::~PolymorphicStructTypeTemplateEntity()
147 throw ()
150 ExceptionTypeEntity::~ExceptionTypeEntity() throw () {}
152 InterfaceTypeEntity::~InterfaceTypeEntity() throw () {}
154 TypedefEntity::~TypedefEntity() throw () {}
156 ConstantGroupEntity::~ConstantGroupEntity() throw () {}
158 SingleInterfaceBasedServiceEntity::~SingleInterfaceBasedServiceEntity() throw ()
161 AccumulationBasedServiceEntity::~AccumulationBasedServiceEntity() throw () {}
163 InterfaceBasedSingletonEntity::~InterfaceBasedSingletonEntity() throw () {}
165 ServiceBasedSingletonEntity::~ServiceBasedSingletonEntity() throw () {}
167 Provider::~Provider() throw () {}
169 rtl::Reference< Provider > Manager::addProvider(OUString const & uri) {
170 rtl::Reference< Provider > p(loadProvider(uri));
171 assert(p.is());
173 osl::MutexGuard g(mutex_);
174 providers_.push_back(p);
176 return p;
179 rtl::Reference< Entity > Manager::findEntity(rtl::OUString const & name) const {
180 //TODO: caching? (here or in cppuhelper::TypeManager?)
181 osl::MutexGuard g(mutex_);
182 for (std::vector< rtl::Reference< Provider > >::const_iterator i(
183 providers_.begin());
184 i != providers_.end(); ++i)
186 rtl::Reference< Entity > ent((*i)->findEntity(name));
187 if (ent.is()) {
188 return ent;
191 return rtl::Reference< Entity >();
194 rtl::Reference< MapCursor > Manager::createCursor(rtl::OUString const & name)
195 const
197 return new AggregatingCursor(providers_, name);
200 Manager::~Manager() throw () {}
202 rtl::Reference< Provider > Manager::loadProvider(OUString const & uri) {
203 osl::DirectoryItem item;
204 if (osl::DirectoryItem::get(uri, item) == osl::FileBase::E_None) {
205 osl::FileStatus status(osl_FileStatus_Mask_Type);
206 if (item.getFileStatus(status) == osl::FileBase::E_None
207 && status.getFileType() == osl::FileStatus::Directory)
209 return new detail::SourceTreeProvider(*this, uri);
212 if (uri.endsWith(".idl")) {
213 return new detail::SourceFileProvider(this, uri);
215 try {
216 return new detail::UnoidlProvider(uri);
217 } catch (FileFormatException & e) {
218 SAL_INFO(
219 "unoidl",
220 "FileFormatException \"" << e.getDetail() << "\", retrying <" << uri
221 << "> as legacy format");
222 return new detail::LegacyProvider(*this, uri);
228 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */