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 {
192  return { "com.sun.star.office.Acceptor" };
193 }
194 
195 sal_Bool Acceptor::supportsService(OUString const & ServiceName)
196 {
197  return cppu::supportsService(this, ServiceName);
198 }
199 
200 
201 // InstanceProvider
203  : m_rContext(rxContext)
204 {
205 }
206 
208 {
209 }
210 
212 {
213 
214  Reference<XInterface> rInstance;
215 
216  if ( aName == "StarOffice.ServiceManager" )
217  {
218  rInstance.set( m_rContext->getServiceManager() );
219  }
220  else if ( aName == "StarOffice.ComponentContext" )
221  {
222  rInstance = m_rContext;
223  }
224  else if ( aName == "StarOffice.NamingService" )
225  {
226  Reference< XNamingService > rNamingService(
227  m_rContext->getServiceManager()->createInstanceWithContext("com.sun.star.uno.NamingService", m_rContext),
228  UNO_QUERY );
229  if ( rNamingService.is() )
230  {
231  rNamingService->registerObject( "StarOffice.ServiceManager", m_rContext->getServiceManager() );
232  rNamingService->registerObject( "StarOffice.ComponentContext", m_rContext );
233  rInstance = rNamingService;
234  }
235  }
236  return rInstance;
237 }
238 
239 }
240 
241 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
243  css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
244 {
245  return cppu::acquire(new desktop::Acceptor(context));
246 }
247 
248 
249 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::uno::XComponentContext > m_rContext
Definition: acceptor.hxx:83
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getInstance(const OUString &aName) override
Definition: acceptor.cxx:211
OUString m_aProtocol
Definition: acceptor.hxx:60
OUString m_aAcceptString
Definition: acceptor.hxx:58
virtual ~AccInstanceProvider() override
Definition: acceptor.cxx:207
OUString m_aConnectString
Definition: acceptor.hxx:59
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:161
AccInstanceProvider(const css::uno::Reference< css::uno::XComponentContext > &rxContext)
Definition: acceptor.cxx:202
virtual OUString SAL_CALL getImplementationName() override
Definition: acceptor.cxx:186
css::uno::Reference< css::bridge::XBridgeFactory2 > m_rBridgeFactory
Definition: acceptor.hxx:56
const Reference< XComponentContext > & m_rContext
oslThread m_thread
Definition: acceptor.hxx:49
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:54
virtual ~Acceptor() override
Definition: acceptor.cxx:63
comphelper::WeakBag< css::bridge::XBridge > m_bridges
Definition: acceptor.hxx:50
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:135
osl::Mutex m_aMutex
Definition: acceptor.hxx:47
#define SAL_INFO(area, stream)
::osl::Condition m_cEnable
Definition: acceptor.hxx:52
void dispose()
css::uno::Reference< css::connection::XAcceptor > m_rAcceptor
Definition: acceptor.hxx:55
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * desktop_Acceptor_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
Definition: acceptor.cxx:242
virtual sal_Bool SAL_CALL supportsService(const OUString &aName) override
Definition: acceptor.cxx:195
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: acceptor.cxx:190