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