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 <osl/file.hxx>
18 #include <osl/mutex.hxx>
19 #include <rtl/ref.hxx>
20 #include <rtl/ustring.hxx>
21 #include <unoidl/unoidl.hxx>
23 #include "legacyprovider.hxx"
24 #include "sourcefileprovider.hxx"
25 #include "sourcetreeprovider.hxx"
26 #include "unoidlprovider.hxx"
32 class AggregatingModule
: public ModuleEntity
{
35 std::vector
< rtl::Reference
< Provider
> > const & providers
,
36 OUString
const & name
):
37 providers_(providers
), name_(name
)
41 virtual ~AggregatingModule() throw () override
{}
43 virtual std::vector
< OUString
> getMemberNames() const override
;
45 virtual rtl::Reference
< MapCursor
> createCursor() const override
;
47 std::vector
< rtl::Reference
< Provider
> > providers_
;
51 std::vector
< OUString
> AggregatingModule::getMemberNames() const {
52 std::set
< OUString
> names
;
53 for (auto & i
: providers_
) {
54 rtl::Reference
< Entity
> ent(i
->findEntity(name_
));
55 if (ent
.is() && ent
->getSort() == Entity::SORT_MODULE
) {
56 std::vector
< OUString
> ns(
57 static_cast< ModuleEntity
* >(ent
.get())->getMemberNames());
58 names
.insert(ns
.begin(), ns
.end());
61 return std::vector
< OUString
>(names
.begin(), names
.end());
64 class AggregatingCursor
: public MapCursor
{
67 std::vector
< rtl::Reference
< Provider
> > const & providers
,
68 OUString
const & name
):
69 providers_(providers
), name_(name
), iterator_(providers_
.begin())
73 virtual ~AggregatingCursor() throw () override
{}
75 virtual rtl::Reference
< Entity
> getNext(OUString
* name
) override
;
79 std::vector
< rtl::Reference
< Provider
> > providers_
;
81 std::vector
< rtl::Reference
< Provider
> >::iterator iterator_
;
82 rtl::Reference
< MapCursor
> cursor_
;
83 std::set
< OUString
> seen_
;
86 rtl::Reference
< Entity
> AggregatingCursor::getNext(OUString
* name
) {
87 while (cursor_
.is()) {
89 rtl::Reference
< Entity
> ent(cursor_
->getNext(&n
));
91 if (seen_
.insert(n
).second
) {
92 if (name
!= nullptr) {
95 return ent
->getSort() == Entity::SORT_MODULE
96 ? new AggregatingModule(
97 providers_
, (name_
.isEmpty() ? name_
: name_
+ ".") + n
)
105 return rtl::Reference
< Entity
>();
108 void AggregatingCursor::findCursor() {
109 for (; !cursor_
.is() && iterator_
!= providers_
.end(); ++iterator_
) {
110 if (name_
.isEmpty()) {
111 cursor_
= (*iterator_
)->createRootCursor();
113 rtl::Reference
< Entity
> ent((*iterator_
)->findEntity(name_
));
114 if (ent
.is() && ent
->getSort() == Entity::SORT_MODULE
) {
115 cursor_
= static_cast< ModuleEntity
* >(ent
.get())->
122 rtl::Reference
< MapCursor
> AggregatingModule::createCursor() const {
123 return new AggregatingCursor(providers_
, name_
);
128 NoSuchFileException::~NoSuchFileException() throw () {}
130 FileFormatException::~FileFormatException() throw () {}
132 Entity::~Entity() throw () {}
134 MapCursor::~MapCursor() throw () {}
136 ModuleEntity::~ModuleEntity() throw () {}
138 PublishableEntity::~PublishableEntity() throw () {}
140 EnumTypeEntity::~EnumTypeEntity() throw () {}
142 PlainStructTypeEntity::~PlainStructTypeEntity() throw () {}
144 PolymorphicStructTypeTemplateEntity::~PolymorphicStructTypeTemplateEntity()
148 ExceptionTypeEntity::~ExceptionTypeEntity() throw () {}
150 InterfaceTypeEntity::~InterfaceTypeEntity() throw () {}
152 TypedefEntity::~TypedefEntity() throw () {}
154 ConstantGroupEntity::~ConstantGroupEntity() throw () {}
156 SingleInterfaceBasedServiceEntity::~SingleInterfaceBasedServiceEntity() throw ()
159 AccumulationBasedServiceEntity::~AccumulationBasedServiceEntity() throw () {}
161 InterfaceBasedSingletonEntity::~InterfaceBasedSingletonEntity() throw () {}
163 ServiceBasedSingletonEntity::~ServiceBasedSingletonEntity() throw () {}
165 Provider::~Provider() throw () {}
167 rtl::Reference
< Provider
> Manager::addProvider(OUString
const & uri
) {
168 rtl::Reference
< Provider
> p(loadProvider(uri
));
171 osl::MutexGuard
g(mutex_
);
172 providers_
.push_back(p
);
177 rtl::Reference
< Entity
> Manager::findEntity(OUString
const & name
) const {
178 //TODO: caching? (here or in cppuhelper::TypeManager?)
179 osl::MutexGuard
g(mutex_
);
180 for (auto & i
: providers_
) {
181 rtl::Reference
< Entity
> ent(i
->findEntity(name
));
186 return rtl::Reference
< Entity
>();
189 rtl::Reference
< MapCursor
> Manager::createCursor(OUString
const & name
)
192 return new AggregatingCursor(providers_
, name
);
195 Manager::~Manager() throw () {}
197 rtl::Reference
< Provider
> Manager::loadProvider(OUString
const & uri
) {
198 osl::DirectoryItem item
;
199 if (osl::DirectoryItem::get(uri
, item
) == osl::FileBase::E_None
) {
200 osl::FileStatus
status(osl_FileStatus_Mask_Type
);
201 if (item
.getFileStatus(status
) == osl::FileBase::E_None
202 && status
.getFileType() == osl::FileStatus::Directory
)
204 return new detail::SourceTreeProvider(*this, uri
);
207 if (uri
.endsWith(".idl")) {
208 return new detail::SourceFileProvider(this, uri
);
211 return new detail::UnoidlProvider(uri
);
212 } catch (FileFormatException
& e
) {
215 "FileFormatException \"" << e
.getDetail() << "\", retrying <" << uri
216 << "> as legacy format");
217 return new detail::LegacyProvider(*this, uri
);
223 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */