1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
10 #include <sal/config.h>
11 #include <sal/log.hxx>
17 #include <config_fuzzers.h>
20 #include <osl/file.hxx>
21 #include <osl/mutex.hxx>
22 #include <rtl/ref.hxx>
23 #include <rtl/ustring.hxx>
24 #include <unoidl/unoidl.hxx>
27 #include "legacyprovider.hxx"
29 #include "sourcefileprovider.hxx"
30 #include "sourcetreeprovider.hxx"
31 #include "unoidlprovider.hxx"
37 class AggregatingModule
: public ModuleEntity
{
40 std::vector
< rtl::Reference
< Provider
> >&& providers
,
42 providers_(std::move(providers
)), name_(std::move(name
))
46 virtual ~AggregatingModule() noexcept override
{}
48 virtual std::vector
< OUString
> getMemberNames() const override
;
50 virtual rtl::Reference
< MapCursor
> createCursor() const override
;
52 std::vector
< rtl::Reference
< Provider
> > providers_
;
56 std::vector
< OUString
> AggregatingModule::getMemberNames() const {
57 std::set
< OUString
> names
;
58 for (auto & i
: providers_
) {
59 rtl::Reference
< Entity
> ent(i
->findEntity(name_
));
60 if (ent
.is() && ent
->getSort() == Entity::SORT_MODULE
) {
61 std::vector
< OUString
> ns(
62 static_cast< ModuleEntity
* >(ent
.get())->getMemberNames());
63 names
.insert(ns
.begin(), ns
.end());
66 return std::vector
< OUString
>(names
.begin(), names
.end());
69 class AggregatingCursor
: public MapCursor
{
72 std::vector
< rtl::Reference
< Provider
> >&& providers
,
74 providers_(std::move(providers
)), name_(std::move(name
)), iterator_(providers_
.begin())
78 virtual ~AggregatingCursor() noexcept override
{}
80 virtual rtl::Reference
< Entity
> getNext(OUString
* name
) override
;
84 std::vector
< rtl::Reference
< Provider
> > providers_
;
86 std::vector
< rtl::Reference
< Provider
> >::iterator iterator_
;
87 rtl::Reference
< MapCursor
> cursor_
;
88 std::set
< OUString
> seen_
;
91 rtl::Reference
< Entity
> AggregatingCursor::getNext(OUString
* name
) {
92 while (cursor_
.is()) {
94 rtl::Reference
< Entity
> ent(cursor_
->getNext(&n
));
96 if (seen_
.insert(n
).second
) {
97 if (name
!= nullptr) {
100 return ent
->getSort() == Entity::SORT_MODULE
101 ? new AggregatingModule(
102 std::vector(providers_
), (name_
.isEmpty() ? name_
: name_
+ ".") + n
)
110 return rtl::Reference
< Entity
>();
113 void AggregatingCursor::findCursor() {
114 for (; !cursor_
.is() && iterator_
!= providers_
.end(); ++iterator_
) {
115 if (name_
.isEmpty()) {
116 cursor_
= (*iterator_
)->createRootCursor();
118 rtl::Reference
< Entity
> ent((*iterator_
)->findEntity(name_
));
119 if (ent
.is() && ent
->getSort() == Entity::SORT_MODULE
) {
120 cursor_
= static_cast< ModuleEntity
* >(ent
.get())->
127 rtl::Reference
< MapCursor
> AggregatingModule::createCursor() const {
128 return new AggregatingCursor(std::vector(providers_
), name_
);
133 NoSuchFileException::~NoSuchFileException() noexcept
{}
135 FileFormatException::~FileFormatException() noexcept
{}
137 Entity::~Entity() noexcept
{}
139 MapCursor::~MapCursor() noexcept
{}
141 ModuleEntity::~ModuleEntity() noexcept
{}
143 PublishableEntity::~PublishableEntity() noexcept
{}
145 EnumTypeEntity::~EnumTypeEntity() noexcept
{}
147 PlainStructTypeEntity::~PlainStructTypeEntity() noexcept
{}
149 PolymorphicStructTypeTemplateEntity::~PolymorphicStructTypeTemplateEntity()
153 ExceptionTypeEntity::~ExceptionTypeEntity() noexcept
{}
155 InterfaceTypeEntity::~InterfaceTypeEntity() noexcept
{}
157 TypedefEntity::~TypedefEntity() noexcept
{}
159 ConstantGroupEntity::~ConstantGroupEntity() noexcept
{}
161 SingleInterfaceBasedServiceEntity::~SingleInterfaceBasedServiceEntity() noexcept
164 AccumulationBasedServiceEntity::~AccumulationBasedServiceEntity() noexcept
{}
166 InterfaceBasedSingletonEntity::~InterfaceBasedSingletonEntity() noexcept
{}
168 ServiceBasedSingletonEntity::~ServiceBasedSingletonEntity() noexcept
{}
170 Provider::~Provider() noexcept
{}
172 rtl::Reference
< Provider
> Manager::addProvider(OUString
const & uri
) {
173 rtl::Reference
< Provider
> p(loadProvider(uri
));
176 osl::MutexGuard
g(mutex_
);
177 providers_
.push_back(p
);
182 rtl::Reference
< Entity
> Manager::findEntity(OUString
const & name
) const {
183 //TODO: caching? (here or in cppuhelper::TypeManager?)
184 osl::MutexGuard
g(mutex_
);
185 for (auto & i
: providers_
) {
186 rtl::Reference
< Entity
> ent(i
->findEntity(name
));
191 return rtl::Reference
< Entity
>();
194 rtl::Reference
< MapCursor
> Manager::createCursor(OUString
const & name
)
197 return new AggregatingCursor(std::vector(providers_
), name
);
200 Manager::~Manager() noexcept
{}
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
);
216 return new detail::UnoidlProvider(uri
);
217 } catch (FileFormatException
& e
) {
221 "FileFormatException \"" << e
.getDetail() << "\", retrying <" << uri
222 << "> as legacy format");
223 return new detail::LegacyProvider(*this, uri
);
233 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */