1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_desktop.hxx" 26 27 #include "acceptor.hxx" 28 #include <unotools/bootstrap.hxx> 29 #include <vos/process.hxx> 30 #include <tools/urlobj.hxx> 31 #include <tools/stream.hxx> 32 #include <vcl/svapp.hxx> 33 #include <com/sun/star/beans/XPropertySet.hpp> 34 #ifndef _COM_SUN_STAR_UNO_XNAMEINGSERVICE_HPP_ 35 #include <com/sun/star/uno/XNamingService.hpp> 36 #endif 37 38 #include <cppuhelper/factory.hxx> 39 40 namespace desktop 41 { 42 43 extern "C" void workerfunc (void * acc) 44 { 45 ((Acceptor*)acc)->run(); 46 } 47 48 static Reference<XInterface> getComponentContext( const Reference<XMultiServiceFactory>& rFactory) 49 { 50 Reference<XInterface> rContext; 51 Reference< XPropertySet > rPropSet( rFactory, UNO_QUERY ); 52 Any a = rPropSet->getPropertyValue( 53 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ); 54 a >>= rContext; 55 return rContext; 56 } 57 58 Mutex Acceptor::m_aMutex; 59 60 Acceptor::Acceptor( const Reference< XMultiServiceFactory >& rFactory ) 61 : m_thread(NULL) 62 , m_aAcceptString() 63 , m_aConnectString() 64 , m_aProtocol() 65 , m_bInit(sal_False) 66 , m_bDying(false) 67 { 68 m_rSMgr = rFactory; 69 m_rAcceptor = Reference< XAcceptor > (m_rSMgr->createInstance( 70 rtl::OUString::createFromAscii( "com.sun.star.connection.Acceptor" )), 71 UNO_QUERY ); 72 m_rBridgeFactory = Reference < XBridgeFactory > (m_rSMgr->createInstance( 73 rtl::OUString::createFromAscii( "com.sun.star.bridge.BridgeFactory" )), 74 UNO_QUERY ); 75 // get component context 76 m_rContext = getComponentContext(m_rSMgr); 77 } 78 79 80 Acceptor::~Acceptor() 81 { 82 m_rAcceptor->stopAccepting(); 83 oslThread t; 84 { 85 osl::MutexGuard g(m_aMutex); 86 t = m_thread; 87 } 88 //prevent locking if the thread is still waiting 89 m_bDying = true; 90 m_cEnable.set(); 91 osl_joinWithThread(t); 92 osl_destroyThread(t); 93 { 94 // Make the final state of m_bridges visible to this thread (since 95 // m_thread is joined, the code that follows is the only one left 96 // accessing m_bridges): 97 osl::MutexGuard g(m_aMutex); 98 } 99 for (;;) { 100 com::sun::star::uno::Reference< com::sun::star::bridge::XBridge > b( 101 m_bridges.remove()); 102 if (!b.is()) { 103 break; 104 } 105 com::sun::star::uno::Reference< com::sun::star::lang::XComponent >( 106 b, com::sun::star::uno::UNO_QUERY_THROW)->dispose(); 107 } 108 } 109 110 void SAL_CALL Acceptor::run() 111 { 112 while ( m_rAcceptor.is() && m_rBridgeFactory.is() ) 113 { 114 RTL_LOGFILE_CONTEXT( aLog, "desktop (lo119109) Acceptor::run" ); 115 try 116 { 117 // wait until we get enabled 118 RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109)"\ 119 "Acceptor::run waiting for office to come up"); 120 m_cEnable.wait(); 121 if (m_bDying) //see destructor 122 break; 123 RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109)"\ 124 "Acceptor::run now enabled and continuing"); 125 126 // accept connection 127 Reference< XConnection > rConnection = m_rAcceptor->accept( m_aConnectString ); 128 // if we return without a valid connection we must assume that the acceptor 129 // is destructed so we break out of the run method terminating the thread 130 if (! rConnection.is()) break; 131 OUString aDescription = rConnection->getDescription(); 132 RTL_LOGFILE_CONTEXT_TRACE1( aLog, "desktop (lo119109) Acceptor::run connection %s", 133 OUStringToOString(aDescription, RTL_TEXTENCODING_ASCII_US).getStr()); 134 135 // create instanceprovider for this connection 136 Reference< XInstanceProvider > rInstanceProvider( 137 (XInstanceProvider*)new AccInstanceProvider(m_rSMgr, rConnection)); 138 // create the bridge. The remote end will have a reference to this bridge 139 // thus preventing the bridge from being disposed. When the remote end releases 140 // the bridge, it will be destructed. 141 Reference< XBridge > rBridge = m_rBridgeFactory->createBridge( 142 rtl::OUString() ,m_aProtocol ,rConnection ,rInstanceProvider ); 143 osl::MutexGuard g(m_aMutex); 144 m_bridges.add(rBridge); 145 } catch (Exception&) { 146 // connection failed... 147 // something went wrong during connection setup. 148 // just wait for a new connection to accept 149 } 150 } 151 } 152 153 // XInitialize 154 void SAL_CALL Acceptor::initialize( const Sequence<Any>& aArguments ) 155 throw( Exception ) 156 { 157 // prevent multiple initialization 158 ClearableMutexGuard aGuard( m_aMutex ); 159 RTL_LOGFILE_CONTEXT( aLog, "destop (lo119109) Acceptor::initialize()" ); 160 161 sal_Bool bOk = sal_False; 162 163 // arg count 164 int nArgs = aArguments.getLength(); 165 166 // not yet initialized and acceptstring 167 if (!m_bInit && nArgs > 0 && (aArguments[0] >>= m_aAcceptString)) 168 { 169 RTL_LOGFILE_CONTEXT_TRACE1( aLog, "desktop (lo119109) Acceptor::initialize string=%s", 170 OUStringToOString(m_aAcceptString, RTL_TEXTENCODING_ASCII_US).getStr()); 171 172 // get connect string and protocol from accept string 173 // "<connectString>;<protocol>" 174 sal_Int32 nIndex1 = m_aAcceptString.indexOf( (sal_Unicode) ';' ); 175 if (nIndex1 < 0) throw IllegalArgumentException( 176 OUString::createFromAscii("Invalid accept-string format"), m_rContext, 1); 177 m_aConnectString = m_aAcceptString.copy( 0 , nIndex1 ).trim(); 178 nIndex1++; 179 sal_Int32 nIndex2 = m_aAcceptString.indexOf( (sal_Unicode) ';' , nIndex1 ); 180 if (nIndex2 < 0) nIndex2 = m_aAcceptString.getLength(); 181 m_aProtocol = m_aAcceptString.copy( nIndex1, nIndex2 - nIndex1 ); 182 183 // start accepting in new thread... 184 m_thread = osl_createThread(workerfunc, this); 185 m_bInit = sal_True; 186 bOk = sal_True; 187 } 188 189 // do we want to enable accepting? 190 sal_Bool bEnable = sal_False; 191 if (((nArgs == 1 && (aArguments[0] >>= bEnable)) || 192 (nArgs == 2 && (aArguments[1] >>= bEnable))) && 193 bEnable ) 194 { 195 m_cEnable.set(); 196 bOk = sal_True; 197 } 198 199 if (!bOk) 200 { 201 throw IllegalArgumentException( 202 OUString::createFromAscii("invalid initialization"), m_rContext, 1); 203 } 204 } 205 206 // XServiceInfo 207 const sal_Char *Acceptor::serviceName = "com.sun.star.office.Acceptor"; 208 const sal_Char *Acceptor::implementationName = "com.sun.star.office.comp.Acceptor"; 209 const sal_Char *Acceptor::supportedServiceNames[] = {"com.sun.star.office.Acceptor", NULL}; 210 OUString Acceptor::impl_getImplementationName() 211 { 212 return OUString::createFromAscii( implementationName ); 213 } 214 OUString SAL_CALL Acceptor::getImplementationName() 215 throw (RuntimeException) 216 { 217 return Acceptor::impl_getImplementationName(); 218 } 219 Sequence<OUString> Acceptor::impl_getSupportedServiceNames() 220 { 221 Sequence<OUString> aSequence; 222 for (int i=0; supportedServiceNames[i]!=NULL; i++) { 223 aSequence.realloc(i+1); 224 aSequence[i]=(OUString::createFromAscii(supportedServiceNames[i])); 225 } 226 return aSequence; 227 } 228 Sequence<OUString> SAL_CALL Acceptor::getSupportedServiceNames() 229 throw (RuntimeException) 230 { 231 return Acceptor::impl_getSupportedServiceNames(); 232 } 233 sal_Bool SAL_CALL Acceptor::supportsService( const OUString&) 234 throw (RuntimeException) 235 { 236 return sal_False; 237 } 238 239 // Factory 240 Reference< XInterface > Acceptor::impl_getInstance( const Reference< XMultiServiceFactory >& aFactory ) 241 { 242 try { 243 return (XComponent*) new Acceptor( aFactory ); 244 } catch ( Exception& ) { 245 return (XComponent*) NULL; 246 } 247 } 248 249 // InstanceProvider 250 AccInstanceProvider::AccInstanceProvider(const Reference<XMultiServiceFactory>& aFactory, const Reference<XConnection>& rConnection) 251 { 252 m_rSMgr = aFactory; 253 m_rConnection = rConnection; 254 } 255 256 AccInstanceProvider::~AccInstanceProvider() 257 { 258 } 259 260 Reference<XInterface> SAL_CALL AccInstanceProvider::getInstance (const OUString& aName ) 261 throw ( NoSuchElementException ) 262 { 263 264 Reference<XInterface> rInstance; 265 266 if ( aName.compareToAscii( "StarOffice.ServiceManager" ) == 0) 267 { 268 rInstance = Reference< XInterface >( m_rSMgr ); 269 } 270 else if(aName.compareToAscii( "StarOffice.ComponentContext" ) == 0 ) 271 { 272 rInstance = getComponentContext( m_rSMgr ); 273 } 274 else if ( aName.compareToAscii("StarOffice.NamingService" ) == 0 ) 275 { 276 Reference< XNamingService > rNamingService( 277 m_rSMgr->createInstance( OUString::createFromAscii( "com.sun.star.uno.NamingService" )), 278 UNO_QUERY ); 279 if ( rNamingService.is() ) 280 { 281 rNamingService->registerObject( 282 OUString::createFromAscii( "StarOffice.ServiceManager" ), m_rSMgr ); 283 rNamingService->registerObject( 284 OUString::createFromAscii( "StarOffice.ComponentContext" ), getComponentContext( m_rSMgr )); 285 rInstance = rNamingService; 286 } 287 } 288 /* 289 else if ( aName.compareToAscii("com.sun.star.ucb.RemoteContentProviderAcceptor" )) 290 { 291 Reference< XMultiServiceFactory > rSMgr = ::comphelper::getProcessServiceFactory(); 292 if ( rSMgr.is() ) { 293 try { 294 rInstance = rSMgr->createInstance( sObjectName ); 295 } 296 catch (Exception const &) {} 297 } 298 } 299 */ 300 return rInstance; 301 } 302 303 } 304 305 // component management stuff... 306 // ---------------------------------------------------------------------------- 307 extern "C" 308 { 309 using namespace desktop; 310 311 void SAL_CALL 312 component_getImplementationEnvironment(const sal_Char **ppEnvironmentTypeName, uno_Environment **) 313 { 314 *ppEnvironmentTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ; 315 } 316 317 void * SAL_CALL 318 component_getFactory(const sal_Char *pImplementationName, void *pServiceManager, void *) 319 { 320 void* pReturn = NULL ; 321 if ( pImplementationName && pServiceManager ) 322 { 323 // Define variables which are used in following macros. 324 Reference< XSingleServiceFactory > xFactory; 325 Reference< XMultiServiceFactory > xServiceManager( 326 reinterpret_cast< XMultiServiceFactory* >(pServiceManager)); 327 328 if (Acceptor::impl_getImplementationName().compareToAscii( pImplementationName ) == COMPARE_EQUAL ) 329 { 330 xFactory = Reference< XSingleServiceFactory >( cppu::createSingleFactory( 331 xServiceManager, Acceptor::impl_getImplementationName(), 332 Acceptor::impl_getInstance, Acceptor::impl_getSupportedServiceNames()) ); 333 } 334 335 // Factory is valid - service was found. 336 if ( xFactory.is() ) 337 { 338 xFactory->acquire(); 339 pReturn = xFactory.get(); 340 } 341 } 342 343 // Return with result of this operation. 344 return pReturn ; 345 } 346 347 } // extern "C" 348