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>
27 #include <sal/log.hxx>
28 #include <tools/diagnose_ex.h>
29 #include <o3tl/string_view.hxx>
30 
31 using namespace css::bridge;
32 using namespace css::connection;
33 using namespace css::lang;
34 using namespace css::uno;
35 
36 namespace desktop
37 {
38 
39 extern "C" {
40 
41 static void offacc_workerfunc (void * acc)
42 {
43  osl_setThreadName("URP Acceptor");
44 
45  static_cast<Acceptor*>(acc)->run();
46 }
47 
48 }
49 
50 Acceptor::Acceptor( const Reference< XComponentContext >& rxContext )
51  : m_thread(nullptr)
52  , m_rContext(rxContext)
53  , m_bInit(false)
54  , m_bDying(false)
55 {
58 }
59 
60 
62 {
63  m_rAcceptor->stopAccepting();
64  oslThread t;
65  {
66  std::unique_lock g(m_aMutex);
67  t = m_thread;
68  }
69  //prevent locking if the thread is still waiting
70  m_bDying = true;
71  m_cEnable.set();
72  osl_joinWithThread(t);
73  osl_destroyThread(t);
74  {
75  // Make the final state of m_bridges visible to this thread (since
76  // m_thread is joined, the code that follows is the only one left
77  // accessing m_bridges):
78  std::unique_lock g(m_aMutex);
79  }
80  for (;;) {
81  css::uno::Reference< css::bridge::XBridge > b(m_bridges.remove());
82  if (!b.is()) {
83  break;
84  }
85  css::uno::Reference< css::lang::XComponent >(
86  b, css::uno::UNO_QUERY_THROW)->dispose();
87  }
88 }
89 
91 {
92  SAL_INFO( "desktop.offacc", "Acceptor::run" );
93  for (;;)
94  {
95  try
96  {
97  // wait until we get enabled
98  SAL_INFO( "desktop.offacc",
99  "Acceptor::run waiting for office to come up");
100  m_cEnable.wait();
101  if (m_bDying) //see destructor
102  break;
103  SAL_INFO( "desktop.offacc",
104  "Acceptor::run now enabled and continuing");
105 
106  // accept connection
107  Reference< XConnection > rConnection = m_rAcceptor->accept( m_aConnectString );
108  // if we return without a valid connection we must assume that the acceptor
109  // is destructed so we break out of the run method terminating the thread
110  if (! rConnection.is()) break;
111  OUString aDescription = rConnection->getDescription();
112  SAL_INFO( "desktop.offacc", "Acceptor::run connection " << aDescription );
113 
114  // create instanceprovider for this connection
115  Reference< XInstanceProvider > rInstanceProvider(new AccInstanceProvider(m_rContext));
116  // create the bridge. The remote end will have a reference to this bridge
117  // thus preventing the bridge from being disposed. When the remote end releases
118  // the bridge, it will be destructed.
119  Reference< XBridge > rBridge = m_rBridgeFactory->createBridge(
120  "", m_aProtocol, rConnection, rInstanceProvider);
121  std::unique_lock g(m_aMutex);
122  m_bridges.add(rBridge);
123  } catch (const Exception&) {
124  TOOLS_WARN_EXCEPTION("desktop.offacc", "");
125  // connection failed...
126  // something went wrong during connection setup.
127  // just wait for a new connection to accept
128  }
129  }
130 }
131 
132 // XInitialize
133 void Acceptor::initialize( const Sequence<Any>& aArguments )
134 {
135  // prevent multiple initialization
136  std::unique_lock aGuard( m_aMutex );
137  SAL_INFO( "desktop.offacc", "Acceptor::initialize()" );
138 
139  bool bOk = false;
140 
141  // arg count
142  int nArgs = aArguments.getLength();
143 
144  // not yet initialized and accept-string
145  if (!m_bInit && nArgs > 0 && (aArguments[0] >>= m_aAcceptString))
146  {
147  SAL_INFO( "desktop.offacc", "Acceptor::initialize string=" << m_aAcceptString );
148 
149  // get connect string and protocol from accept string
150  // "<connectString>;<protocol>"
151  sal_Int32 nIndex1 = m_aAcceptString.indexOf( ';' );
152  if (nIndex1 < 0)
153  throw IllegalArgumentException(
154  "Invalid accept-string format", m_rContext, 1);
155  m_aConnectString = o3tl::trim(m_aAcceptString.subView( 0 , nIndex1 ));
156  nIndex1++;
157  sal_Int32 nIndex2 = m_aAcceptString.indexOf( ';' , nIndex1 );
158  if (nIndex2 < 0) nIndex2 = m_aAcceptString.getLength();
159  m_aProtocol = m_aAcceptString.copy( nIndex1, nIndex2 - nIndex1 );
160 
161  // start accepting in new thread...
162  m_thread = osl_createThread(offacc_workerfunc, this);
163  m_bInit = true;
164  bOk = true;
165  }
166 
167  // do we want to enable accepting?
168  bool bEnable = false;
169  if (((nArgs == 1 && (aArguments[0] >>= bEnable)) ||
170  (nArgs == 2 && (aArguments[1] >>= bEnable))) &&
171  bEnable )
172  {
173  m_cEnable.set();
174  bOk = true;
175  }
176 
177  if (!bOk)
178  {
179  throw IllegalArgumentException( "invalid initialization", m_rContext, 1);
180  }
181 }
182 
183 // XServiceInfo
185 {
186  return "com.sun.star.office.comp.Acceptor";
187 }
189 {
190  return { "com.sun.star.office.Acceptor" };
191 }
192 
193 sal_Bool Acceptor::supportsService(OUString const & ServiceName)
194 {
195  return cppu::supportsService(this, ServiceName);
196 }
197 
198 
199 // InstanceProvider
201  : m_rContext(rxContext)
202 {
203 }
204 
206 {
207 }
208 
209 Reference<XInterface> AccInstanceProvider::getInstance (const OUString& aName )
210 {
211 
212  Reference<XInterface> rInstance;
213 
214  if ( aName == "StarOffice.ServiceManager" )
215  {
216  rInstance.set( m_rContext->getServiceManager() );
217  }
218  else if ( aName == "StarOffice.ComponentContext" )
219  {
220  rInstance = m_rContext;
221  }
222  else if ( aName == "StarOffice.NamingService" )
223  {
224  Reference< XNamingService > rNamingService(
225  m_rContext->getServiceManager()->createInstanceWithContext("com.sun.star.uno.NamingService", m_rContext),
226  UNO_QUERY );
227  if ( rNamingService.is() )
228  {
229  rNamingService->registerObject( "StarOffice.ServiceManager", m_rContext->getServiceManager() );
230  rNamingService->registerObject( "StarOffice.ComponentContext", m_rContext );
231  rInstance = rNamingService;
232  }
233  }
234  return rInstance;
235 }
236 
237 }
238 
239 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
241  css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
242 {
243  return cppu::acquire(new desktop::Acceptor(context));
244 }
245 
246 
247 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::uno::XComponentContext > m_rContext
Definition: acceptor.hxx:82
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getInstance(const OUString &aName) override
Definition: acceptor.cxx:209
OUString m_aProtocol
Definition: acceptor.hxx:59
OUString m_aAcceptString
Definition: acceptor.hxx:57
virtual ~AccInstanceProvider() override
Definition: acceptor.cxx:205
OUString m_aConnectString
Definition: acceptor.hxx:58
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:164
AccInstanceProvider(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
Definition: acceptor.cxx:200
virtual OUString SAL_CALL getImplementationName() override
Definition: acceptor.cxx:184
css::uno::Reference< css::bridge::XBridgeFactory2 > m_rBridgeFactory
Definition: acceptor.hxx:55
const Reference< XComponentContext > & m_rContext
oslThread m_thread
Definition: acceptor.hxx:48
static void offacc_workerfunc(void *acc)
Definition: acceptor.cxx:41
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
def run
css::uno::Reference< T > remove()
std::mutex m_aMutex
Definition: acceptor.hxx:46
#define TOOLS_WARN_EXCEPTION(area, stream)
css::uno::Reference< css::uno::XComponentContext > m_rContext
Definition: acceptor.hxx:53
virtual ~Acceptor() override
Definition: acceptor.cxx:61
comphelper::WeakBag< css::bridge::XBridge > m_bridges
Definition: acceptor.hxx:49
unsigned char sal_Bool
XPropertyListType t
void add(css::uno::Reference< T > const &e)
virtual void SAL_CALL initialize(const css::uno::Sequence< css::uno::Any > &aArguments) override
Definition: acceptor.cxx:133
#define SAL_INFO(area, stream)
std::u16string_view trim(std::u16string_view str)
::osl::Condition m_cEnable
Definition: acceptor.hxx:51
void dispose()
css::uno::Reference< css::connection::XAcceptor > m_rAcceptor
Definition: acceptor.hxx:54
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * desktop_Acceptor_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
Definition: acceptor.cxx:240
virtual sal_Bool SAL_CALL supportsService(const OUString &aName) override
Definition: acceptor.cxx:193
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: acceptor.cxx:188
bool m_bDetectedRangeSegmentation false