1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "sal/config.h"
25 
26 #include <algorithm>
27 
28 #include "com/sun/star/connection/XConnection.hpp"
29 #include "com/sun/star/uno/Exception.hpp"
30 #include "com/sun/star/uno/Reference.hxx"
31 #include "com/sun/star/uno/RuntimeException.hpp"
32 #include "com/sun/star/uno/XComponentContext.hpp"
33 #include "com/sun/star/uno/XInterface.hpp"
34 #include "cppuhelper/factory.hxx"
35 #include "cppuhelper/implementationentry.hxx"
36 #include "osl/diagnose.h"
37 #include "rtl/ref.hxx"
38 #include "sal/types.h"
39 #include "uno/lbnames.h"
40 
41 #include "bridge.hxx"
42 #include "bridgefactory.hxx"
43 
44 namespace binaryurp {
45 
46 namespace {
47 
48 namespace css = com::sun::star;
49 
50 }
51 
52 css::uno::Reference< css::uno::XInterface > BridgeFactory::static_create(
53     css::uno::Reference< css::uno::XComponentContext > const & xContext)
54     SAL_THROW((css::uno::Exception))
55 {
56     return static_cast< cppu::OWeakObject * >(new BridgeFactory(xContext));
57 }
58 
59 rtl::OUString BridgeFactory::static_getImplementationName() {
60     return rtl::OUString(
61         RTL_CONSTASCII_USTRINGPARAM(
62             "com.sun.star.comp.bridge.BridgeFactory"));
63 }
64 
65 css::uno::Sequence< rtl::OUString >
66 BridgeFactory::static_getSupportedServiceNames() {
67     rtl::OUString name(
68         RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.BridgeFactory"));
69     return css::uno::Sequence< rtl::OUString >(&name, 1);
70 }
71 
72 void BridgeFactory::removeBridge(
73     css::uno::Reference< css::bridge::XBridge > const & bridge)
74 {
75     OSL_ASSERT(bridge.is());
76     rtl::OUString n(bridge->getName());
77     osl::MutexGuard g(*this);
78     if (n.getLength() == 0) {
79         BridgeList::iterator i(
80             std::find(unnamed_.begin(), unnamed_.end(), bridge));
81         if (i != unnamed_.end()) {
82             unnamed_.erase(i);
83         }
84     } else {
85         BridgeMap::iterator i(named_.find(n));
86         if (i != named_.end() && i->second == bridge) {
87             named_.erase(i);
88         }
89     }
90 }
91 
92 BridgeFactory::BridgeFactory(
93     css::uno::Reference< css::uno::XComponentContext > const & context):
94     BridgeFactoryBase(*static_cast< osl::Mutex * >(this)), context_(context)
95 {
96     OSL_ASSERT(context.is());
97 }
98 
99 BridgeFactory::~BridgeFactory() {}
100 
101 rtl::OUString BridgeFactory::getImplementationName()
102     throw (css::uno::RuntimeException)
103 {
104     return static_getImplementationName();
105 }
106 
107 sal_Bool BridgeFactory::supportsService(rtl::OUString const & ServiceName)
108     throw (css::uno::RuntimeException)
109 {
110     css::uno::Sequence< rtl::OUString > s(getSupportedServiceNames());
111     for (sal_Int32 i = 0; i != s.getLength(); ++i) {
112         if (ServiceName == s[i]) {
113             return true;
114         }
115     }
116     return false;
117 }
118 
119 css::uno::Sequence< rtl::OUString > BridgeFactory::getSupportedServiceNames()
120     throw (css::uno::RuntimeException)
121 {
122     return static_getSupportedServiceNames();
123 }
124 
125 css::uno::Reference< css::bridge::XBridge > BridgeFactory::createBridge(
126     rtl::OUString const & sName, rtl::OUString const & sProtocol,
127     css::uno::Reference< css::connection::XConnection > const & aConnection,
128     css::uno::Reference< css::bridge::XInstanceProvider > const &
129         anInstanceProvider)
130     throw (
131         css::bridge::BridgeExistsException, css::lang::IllegalArgumentException,
132         css::uno::RuntimeException)
133 {
134     rtl::Reference< Bridge > b;
135     {
136         osl::MutexGuard g(*this);
137         if (named_.find(sName) != named_.end()) {
138             throw css::bridge::BridgeExistsException(
139                 sName, static_cast< cppu::OWeakObject * >(this));
140         }
141         if (!(sProtocol.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("urp")) &&
142               aConnection.is()))
143         {
144             throw css::lang::IllegalArgumentException(
145                 rtl::OUString(
146                     RTL_CONSTASCII_USTRINGPARAM(
147                         "BridgeFactory::createBridge: sProtocol != urp ||"
148                         " aConnection == null")),
149                 static_cast< cppu::OWeakObject * >(this), -1);
150         }
151         b.set(new Bridge(this, sName, aConnection, anInstanceProvider));
152         if (sName.getLength() == 0) {
153             unnamed_.push_back(
154                 css::uno::Reference< css::bridge::XBridge >(b.get()));
155         } else {
156             named_[sName] = b.get();
157         }
158     }
159     b->start();
160     return css::uno::Reference< css::bridge::XBridge >(b.get());
161 }
162 
163 css::uno::Reference< css::bridge::XBridge > BridgeFactory::getBridge(
164     rtl::OUString const & sName) throw (css::uno::RuntimeException)
165 {
166     osl::MutexGuard g(*this);
167     BridgeMap::iterator i(named_.find(sName));
168     return i == named_.end()
169         ? css::uno::Reference< css::bridge::XBridge >() : i->second;
170 }
171 
172 css::uno::Sequence< css::uno::Reference< css::bridge::XBridge > >
173 BridgeFactory::getExistingBridges() throw (css::uno::RuntimeException) {
174     osl::MutexGuard g(*this);
175     if (unnamed_.size() > SAL_MAX_INT32) {
176         throw css::uno::RuntimeException(
177             rtl::OUString(
178                 RTL_CONSTASCII_USTRINGPARAM(
179                     "BridgeFactory::getExistingBridges: too many")),
180             static_cast< cppu::OWeakObject * >(this));
181     }
182     sal_Int32 n = static_cast< sal_Int32 >(unnamed_.size());
183     if (named_.size() > static_cast< sal_uInt32 >(SAL_MAX_INT32 - n)) {
184         throw css::uno::RuntimeException(
185             rtl::OUString(
186                 RTL_CONSTASCII_USTRINGPARAM(
187                     "BridgeFactory::getExistingBridges: too many")),
188             static_cast< cppu::OWeakObject * >(this));
189     }
190     n = static_cast< sal_Int32 >(n + named_.size());
191     css::uno::Sequence< css::uno::Reference< css::bridge::XBridge > > s(n);
192     sal_Int32 i = 0;
193     for (BridgeList::iterator j(unnamed_.begin()); j != unnamed_.end(); ++j) {
194         s[i++] = *j;
195     }
196     for (BridgeMap::iterator j(named_.begin()); j != named_.end(); ++j) {
197         s[i++] = j->second;
198     }
199     return s;
200 }
201 
202 }
203 
204 namespace {
205 
206 static cppu::ImplementationEntry const services[] = {
207     { &binaryurp::BridgeFactory::static_create,
208       &binaryurp::BridgeFactory::static_getImplementationName,
209       &binaryurp::BridgeFactory::static_getSupportedServiceNames,
210       &cppu::createSingleComponentFactory, 0, 0 },
211     { 0, 0, 0, 0, 0, 0 }
212 };
213 
214 }
215 
216 extern "C" SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory(
217     char const * pImplName, void * pServiceManager, void * pRegistryKey)
218 {
219     return cppu::component_getFactoryHelper(
220         pImplName, pServiceManager, pRegistryKey, services);
221 }
222 
223 extern "C" SAL_DLLPUBLIC_EXPORT void SAL_CALL
224 component_getImplementationEnvironment(
225     char const ** ppEnvTypeName, uno_Environment **)
226 {
227     *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
228 }
229