LibreOffice Module desktop (master)  1
acceptor.cxx
Go to the documentation of this file.
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 "acceptor.hxx"
23 #include <com/sun/star/bridge/BridgeFactory.hpp>
24 #include <com/sun/star/connection/Acceptor.hpp>
25 #include <com/sun/star/uno/XNamingService.hpp>
26 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
28 #include <cppuhelper/factory.hxx>
30 #include <sal/log.hxx>
31 
32 using namespace css::bridge;
33 using namespace css::connection;
34 using namespace css::lang;
35 using namespace css::uno;
36 
37 namespace desktop
38 {
39 
40 extern "C" {
41 
42 static void offacc_workerfunc (void * acc)
43 {
44  osl_setThreadName("URP Acceptor");
45 
46  static_cast<Acceptor*>(acc)->run();
47 }
48 
49 }
50 
51 Acceptor::Acceptor( const Reference< XComponentContext >& rxContext )
52  : m_thread(nullptr)
53  , m_rContext(rxContext)
54  , m_bInit(false)
55  , m_bDying(false)
56 {
59 }
60 
61 
63 {
64  m_rAcceptor->stopAccepting();
65  oslThread t;
66  {
67  osl::MutexGuard g(m_aMutex);
68  t = m_thread;
69  }
70  //prevent locking if the thread is still waiting
71  m_bDying = true;
72  m_cEnable.set();
73  osl_joinWithThread(t);
74  osl_destroyThread(t);
75  {
76  // Make the final state of m_bridges visible to this thread (since
77  // m_thread is joined, the code that follows is the only one left
78  // accessing m_bridges):
79  osl::MutexGuard g(m_aMutex);
80  }
81  for (;;) {
82  css::uno::Reference< css::bridge::XBridge > b(m_bridges.remove());
83  if (!b.is()) {
84  break;
85  }
86  css::uno::Reference< css::lang::XComponent >(
87  b, css::uno::UNO_QUERY_THROW)->dispose();
88  }
89 }
90 
92 {
93  SAL_INFO( "desktop.offacc", "Acceptor::run" );
94  for (;;)
95  {
96  try
97  {
98  // wait until we get enabled
99  SAL_INFO( "desktop.offacc",
100  "Acceptor::run waiting for office to come up");
101  m_cEnable.wait();
102  if (m_bDying) //see destructor
103  break;
104  SAL_INFO( "desktop.offacc",
105  "Acceptor::run now enabled and continuing");
106 
107  // accept connection
108  Reference< XConnection > rConnection = m_rAcceptor->accept( m_aConnectString );
109  // if we return without a valid connection we must assume that the acceptor
110  // is destructed so we break out of the run method terminating the thread
111  if (! rConnection.is()) break;
112  OUString aDescription = rConnection->getDescription();
113  SAL_INFO( "desktop.offacc", "Acceptor::run connection " << aDescription );
114 
115  // create instanceprovider for this connection
116  Reference< XInstanceProvider > rInstanceProvider(new AccInstanceProvider(m_rContext));
117  // create the bridge. The remote end will have a reference to this bridge
118  // thus preventing the bridge from being disposed. When the remote end releases
119  // the bridge, it will be destructed.
120  Reference< XBridge > rBridge = m_rBridgeFactory->createBridge(
121  "", m_aProtocol, rConnection, rInstanceProvider);
122  osl::MutexGuard g(m_aMutex);
123  m_bridges.add(rBridge);
124  } catch (const Exception& e) {
125  SAL_WARN("desktop.offacc", "caught " << e);
126  // connection failed...
127  // something went wrong during connection setup.
128  // just wait for a new connection to accept
129  }
130  }
131 }
132 
133 // XInitialize
134 void Acceptor::initialize( const Sequence<Any>& aArguments )
135 {
136  // prevent multiple initialization
137  osl::MutexGuard aGuard( m_aMutex );
138  SAL_INFO( "desktop.offacc", "Acceptor::initialize()" );
139 
140  bool bOk = false;
141 
142  // arg count
143  int nArgs = aArguments.getLength();
144 
145  // not yet initialized and accept-string
146  if (!m_bInit && nArgs > 0 && (aArguments[0] >>= m_aAcceptString))
147  {
148  SAL_INFO( "desktop.offacc", "Acceptor::initialize string=" << m_aAcceptString );
149 
150  // get connect string and protocol from accept string
151  // "<connectString>;<protocol>"
152  sal_Int32 nIndex1 = m_aAcceptString.indexOf( ';' );
153  if (nIndex1 < 0)
154  throw IllegalArgumentException(
155  "Invalid accept-string format", m_rContext, 1);
156  m_aConnectString = m_aAcceptString.copy( 0 , nIndex1 ).trim();
157  nIndex1++;
158  sal_Int32 nIndex2 = m_aAcceptString.indexOf( ';' , nIndex1 );
159  if (nIndex2 < 0) nIndex2 = m_aAcceptString.getLength();
160  m_aProtocol = m_aAcceptString.copy( nIndex1, nIndex2 - nIndex1 );
161 
162  // start accepting in new thread...
163  m_thread = osl_createThread(offacc_workerfunc, this);
164  m_bInit = true;
165  bOk = true;
166  }
167 
168  // do we want to enable accepting?
169  bool bEnable = false;
170  if (((nArgs == 1 && (aArguments[0] >>= bEnable)) ||
171  (nArgs == 2 && (aArguments[1] >>= bEnable))) &&
172  bEnable )
173  {
174  m_cEnable.set();
175  bOk = true;
176  }
177 
178  if (!bOk)
179  {
180  throw IllegalArgumentException( "invalid initialization", m_rContext, 1);
181  }
182 }
183 
184 // XServiceInfo
186 {
187  return OUString("com.sun.star.office.comp.Acceptor");
188 }
190 {
192 }
194 {
195  return { "com.sun.star.office.Acceptor" };
196 }
198 {
200 }
201 
202 sal_Bool Acceptor::supportsService(OUString const & ServiceName)
203 {
204  return cppu::supportsService(this, ServiceName);
205 }
206 
207 // Factory
209 {
210  try {
211  return static_cast<cppu::OWeakObject *>(
213  } catch ( const Exception& ) {
214  return css::uno::Reference<css::uno::XInterface>();
215  }
216 }
217 
218 // InstanceProvider
220 {
221  m_rContext = rxContext;
222 }
223 
225 {
226 }
227 
229 {
230 
231  Reference<XInterface> rInstance;
232 
233  if ( aName == "StarOffice.ServiceManager" )
234  {
235  rInstance.set( m_rContext->getServiceManager() );
236  }
237  else if ( aName == "StarOffice.ComponentContext" )
238  {
239  rInstance = m_rContext;
240  }
241  else if ( aName == "StarOffice.NamingService" )
242  {
243  Reference< XNamingService > rNamingService(
244  m_rContext->getServiceManager()->createInstanceWithContext("com.sun.star.uno.NamingService", m_rContext),
245  UNO_QUERY );
246  if ( rNamingService.is() )
247  {
248  rNamingService->registerObject( "StarOffice.ServiceManager", m_rContext->getServiceManager() );
249  rNamingService->registerObject( "StarOffice.ComponentContext", m_rContext );
250  rInstance = rNamingService;
251  }
252  }
253  return rInstance;
254 }
255 
256 }
257 
258 // component management stuff...
259 
260 extern "C"
261 {
262 using namespace desktop;
263 
264 SAL_DLLPUBLIC_EXPORT void * offacc_component_getFactory(char const *pImplementationName, void *pServiceManager, void *)
265 {
266  void* pReturn = nullptr ;
267  if ( pImplementationName && pServiceManager )
268  {
269  // Define variables which are used in following macros.
270  Reference< XSingleServiceFactory > xFactory;
271  Reference< XMultiServiceFactory > xServiceManager(
272  static_cast< XMultiServiceFactory* >(pServiceManager));
273 
274  if (desktop::Acceptor::impl_getImplementationName().equalsAscii( pImplementationName ) )
275  {
276  xFactory.set( cppu::createSingleFactory(
279  }
280 
281  // Factory is valid - service was found.
282  if ( xFactory.is() )
283  {
284  xFactory->acquire();
285  pReturn = xFactory.get();
286  }
287  }
288 
289  // Return with result of this operation.
290  return pReturn ;
291 }
292 
293 } // extern "C"
294 
295 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::uno::XComponentContext > m_rContext
Definition: acceptor.hxx:94
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getInstance(const OUString &aName) override
Definition: acceptor.cxx:228
OUString m_aProtocol
Definition: acceptor.hxx:67
OUString m_aAcceptString
Definition: acceptor.hxx:65
virtual ~AccInstanceProvider() override
Definition: acceptor.cxx:224
OUString m_aConnectString
Definition: acceptor.hxx:66
css::uno::Reference< css::deployment::XPackageRegistry > create(css::uno::Reference< css::deployment::XPackageRegistry > const &xRootRegistry, OUString const &context, OUString const &cachePath, css::uno::Reference< css::uno::XComponentContext > const &xComponentContext)
Definition: app.cxx:168
AccInstanceProvider(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
Definition: acceptor.cxx:219
virtual OUString SAL_CALL getImplementationName() override
Definition: acceptor.cxx:189
css::uno::Reference< css::bridge::XBridgeFactory2 > m_rBridgeFactory
Definition: acceptor.hxx:63
oslThread m_thread
Definition: acceptor.hxx:56
static void offacc_workerfunc(void *acc)
Definition: acceptor.cxx:42
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
def run
css::uno::Reference< T > remove()
css::uno::Reference< css::uno::XComponentContext > m_rContext
Definition: acceptor.hxx:61
virtual ~Acceptor() override
Definition: acceptor.cxx:62
comphelper::WeakBag< css::bridge::XBridge > m_bridges
Definition: acceptor.hxx:57
unsigned char sal_Bool
Reference< XComponentContext > getComponentContext(Reference< XMultiServiceFactory > const &factory)
css::uno::Reference< css::uno::XInterface >(SAL_CALL *ComponentInstantiation)(const css CPPUHELPER_DLLPUBLIC css::uno::Reference< css::lang::XSingleServiceFactory > SAL_CALL createSingleFactory(const css::uno::Reference< css::lang::XMultiServiceFactory > &rServiceManager, const ::rtl::OUString &rImplementationName, ComponentInstantiation pCreateFunction, const css::uno::Sequence< ::rtl::OUString > &rServiceNames, rtl_ModuleCount *pModCount=NULL)
XPropertyListType t
void add(css::uno::Reference< T > const &e)
static uno::Reference< css::lang::XMultiComponentFactory > xFactory
Definition: init.cxx:1606
virtual void SAL_CALL initialize(const css::uno::Sequence< css::uno::Any > &aArguments) override
Definition: acceptor.cxx:134
osl::Mutex m_aMutex
Definition: acceptor.hxx:54
SAL_DLLPUBLIC_EXPORT void * offacc_component_getFactory(char const *pImplementationName, void *pServiceManager, void *)
Definition: acceptor.cxx:264
#define SAL_INFO(area, stream)
Acceptor(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
Definition: acceptor.cxx:51
::osl::Condition m_cEnable
Definition: acceptor.hxx:59
static OUString impl_getImplementationName()
Definition: acceptor.cxx:185
#define SAL_WARN(area, stream)
static css::uno::Reference< css::uno::XInterface > impl_getInstance(const css::uno::Reference< css::lang::XMultiServiceFactory > &aFactory)
Definition: acceptor.cxx:208
void dispose()
css::uno::Reference< css::connection::XAcceptor > m_rAcceptor
Definition: acceptor.hxx:62
static css::uno::Sequence< OUString > impl_getSupportedServiceNames()
Definition: acceptor.cxx:193
virtual sal_Bool SAL_CALL supportsService(const OUString &aName) override
Definition: acceptor.cxx:202
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: acceptor.cxx:197