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