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