1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <algorithm>
23 #include <cassert>
24 
25 #include <com/sun/star/bridge/BridgeExistsException.hpp>
26 #include <com/sun/star/connection/XConnection.hpp>
27 #include <com/sun/star/lang/IllegalArgumentException.hpp>
28 #include <com/sun/star/uno/Exception.hpp>
29 #include <com/sun/star/uno/Reference.hxx>
30 #include <com/sun/star/uno/RuntimeException.hpp>
31 #include <com/sun/star/uno/XComponentContext.hpp>
32 #include <com/sun/star/uno/XInterface.hpp>
33 #include <cppuhelper/supportsservice.hxx>
34 #include <o3tl/safeint.hxx>
35 #include <rtl/ref.hxx>
36 #include <sal/log.hxx>
37 #include <sal/types.h>
38 
39 #include "bridge.hxx"
40 #include "bridgefactory.hxx"
41 
42 namespace binaryurp {
43 
removeBridge(css::uno::Reference<css::bridge::XBridge> const & bridge)44 void BridgeFactory::removeBridge(
45     css::uno::Reference< css::bridge::XBridge > const & bridge)
46 {
47     assert(bridge.is());
48     OUString n(bridge->getName());
49     osl::MutexGuard g(m_aMutex);
50     if (n.isEmpty())
51     {
52         unnamed_.erase(std::remove(unnamed_.begin(), unnamed_.end(), bridge), unnamed_.end());
53     }
54     else
55     {
56         BridgeMap::iterator i(named_.find(n));
57         if (i != named_.end() && i->second == bridge)
58             named_.erase(i);
59     }
60 }
61 
BridgeFactory()62 BridgeFactory::BridgeFactory():
63     BridgeFactoryBase(m_aMutex)
64 {
65 }
66 
~BridgeFactory()67 BridgeFactory::~BridgeFactory() {}
68 
getImplementationName()69 OUString BridgeFactory::getImplementationName()
70 {
71     return "com.sun.star.comp.bridge.BridgeFactory";
72 }
73 
supportsService(OUString const & ServiceName)74 sal_Bool BridgeFactory::supportsService(OUString const & ServiceName)
75 {
76     return cppu::supportsService(this, ServiceName);
77 }
78 
getSupportedServiceNames()79 css::uno::Sequence< OUString > BridgeFactory::getSupportedServiceNames()
80 {
81     return { "com.sun.star.bridge.BridgeFactory" };
82 }
83 
createBridge(OUString const & sName,OUString const & sProtocol,css::uno::Reference<css::connection::XConnection> const & aConnection,css::uno::Reference<css::bridge::XInstanceProvider> const & anInstanceProvider)84 css::uno::Reference< css::bridge::XBridge > BridgeFactory::createBridge(
85     OUString const & sName, OUString const & sProtocol,
86     css::uno::Reference< css::connection::XConnection > const & aConnection,
87     css::uno::Reference< css::bridge::XInstanceProvider > const &
88         anInstanceProvider)
89 {
90     rtl::Reference< Bridge > b;
91     {
92         osl::MutexGuard g(m_aMutex);
93         if (rBHelper.bDisposed) {
94             throw css::lang::DisposedException(
95                 "BridgeFactory disposed",
96                 static_cast< cppu::OWeakObject * >(this));
97         }
98         if (named_.find(sName) != named_.end()) {
99             throw css::bridge::BridgeExistsException(
100                 sName, static_cast< cppu::OWeakObject * >(this));
101         }
102         if (sProtocol != "urp" || !aConnection.is()) {
103             throw css::lang::IllegalArgumentException(
104                 ("BridgeFactory::createBridge: sProtocol != urp ||"
105                  " aConnection == null"),
106                 static_cast< cppu::OWeakObject * >(this), -1);
107         }
108         b.set(new Bridge(this, sName, aConnection, anInstanceProvider));
109         if (sName.isEmpty()) {
110             unnamed_.emplace_back(b.get());
111         } else {
112             named_[sName] = b.get();
113         }
114     }
115     b->start();
116     return b;
117 }
118 
getBridge(OUString const & sName)119 css::uno::Reference< css::bridge::XBridge > BridgeFactory::getBridge(
120     OUString const & sName)
121 {
122     osl::MutexGuard g(m_aMutex);
123     BridgeMap::iterator i(named_.find(sName));
124     return i == named_.end()
125         ? css::uno::Reference< css::bridge::XBridge >() : i->second;
126 }
127 
128 css::uno::Sequence< css::uno::Reference< css::bridge::XBridge > >
getExistingBridges()129 BridgeFactory::getExistingBridges() {
130     osl::MutexGuard g(m_aMutex);
131     if (unnamed_.size() > SAL_MAX_INT32) {
132         throw css::uno::RuntimeException(
133             "BridgeFactory::getExistingBridges: too many",
134             static_cast< cppu::OWeakObject * >(this));
135     }
136     sal_Int32 n = static_cast< sal_Int32 >(unnamed_.size());
137     if (named_.size() > o3tl::make_unsigned(SAL_MAX_INT32 - n)) {
138         throw css::uno::RuntimeException(
139             "BridgeFactory::getExistingBridges: too many",
140             static_cast< cppu::OWeakObject * >(this));
141     }
142     n = static_cast< sal_Int32 >(n + named_.size());
143     css::uno::Sequence< css::uno::Reference< css::bridge::XBridge > > s(n);
144     sal_Int32 i = 0;
145     for (auto const& item : unnamed_)
146         s[i++] = item;
147 
148     for (auto const& item : named_)
149         s[i++] = item.second;
150 
151     return s;
152 }
153 
disposing()154 void BridgeFactory::disposing() {
155     BridgeVector l1;
156     BridgeMap l2;
157     {
158         osl::MutexGuard g(m_aMutex);
159         l1.swap(unnamed_);
160         l2.swap(named_);
161     }
162     for (auto const& item : l1)
163     {
164         try {
165             css::uno::Reference<css::lang::XComponent>(
166                 item, css::uno::UNO_QUERY_THROW)->dispose();
167         } catch (css::uno::Exception & e) {
168             SAL_WARN("binaryurp", "ignoring " << e);
169         }
170     }
171     for (auto const& item : l2)
172     {
173         try {
174             css::uno::Reference<css::lang::XComponent>(
175                 item.second, css::uno::UNO_QUERY_THROW)->dispose();
176         } catch (css::uno::Exception & e) {
177             SAL_WARN("binaryurp", "ignoring " << e);
178         }
179     }
180 }
181 
182 }
183 
184 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
com_sun_star_comp_bridge_BridgeFactory_get_implementation(css::uno::XComponentContext *,css::uno::Sequence<css::uno::Any> const &)185 com_sun_star_comp_bridge_BridgeFactory_get_implementation(
186     css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
187 {
188     return cppu::acquire(new binaryurp::BridgeFactory);
189 }
190 
191 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
192