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 { 93 // Make the final state of m_bridges visible to this thread (since 94 // m_thread is joined, the code that follows is the only one left 95 // accessing m_bridges): 96 osl::MutexGuard g(m_aMutex); 97 } 98 for (;;) { 99 com::sun::star::uno::Reference< com::sun::star::bridge::XBridge > b( 100 m_bridges.remove()); 101 if (!b.is()) { 102 break; 103 } 104 com::sun::star::uno::Reference< com::sun::star::lang::XComponent >( 105 b, com::sun::star::uno::UNO_QUERY_THROW)->dispose(); 106 } 107 } 108 109 void SAL_CALL Acceptor::run() 110 { 111 while ( m_rAcceptor.is() && m_rBridgeFactory.is() ) 112 { 113 RTL_LOGFILE_CONTEXT( aLog, "desktop (lo119109) Acceptor::run" ); 114 try 115 { 116 // wait until we get enabled 117 RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109)"\ 118 "Acceptor::run waiting for office to come up"); 119 m_cEnable.wait(); 120 if (m_bDying) //see destructor 121 break; 122 RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109)"\ 123 "Acceptor::run now enabled and continuing"); 124 125 // accept connection 126 Reference< XConnection > rConnection = m_rAcceptor->accept( m_aConnectString ); 127 // if we return without a valid connection we must assume that the acceptor 128 // is destructed so we break out of the run method terminating the thread 129 if (! rConnection.is()) break; 130 OUString aDescription = rConnection->getDescription(); 131 RTL_LOGFILE_CONTEXT_TRACE1( aLog, "desktop (lo119109) Acceptor::run connection %s", 132 OUStringToOString(aDescription, RTL_TEXTENCODING_ASCII_US).getStr()); 133 134 // create instanceprovider for this connection 135 Reference< XInstanceProvider > rInstanceProvider( 136 (XInstanceProvider*)new AccInstanceProvider(m_rSMgr, rConnection)); 137 // create the bridge. The remote end will have a reference to this bridge 138 // thus preventing the bridge from being disposed. When the remote end releases 139 // the bridge, it will be destructed. 140 Reference< XBridge > rBridge = m_rBridgeFactory->createBridge( 141 rtl::OUString() ,m_aProtocol ,rConnection ,rInstanceProvider ); 142 osl::MutexGuard g(m_aMutex); 143 m_bridges.add(rBridge); 144 } catch (Exception&) { 145 // connection failed... 146 // something went wrong during connection setup. 147 // just wait for a new connection to accept 148 } 149 } 150 } 151 152 // XInitialize 153 void SAL_CALL Acceptor::initialize( const Sequence<Any>& aArguments ) 154 throw( Exception ) 155 { 156 // prevent multiple initialization 157 ClearableMutexGuard aGuard( m_aMutex ); 158 RTL_LOGFILE_CONTEXT( aLog, "destop (lo119109) Acceptor::initialize()" ); 159 160 sal_Bool bOk = sal_False; 161 162 // arg count 163 int nArgs = aArguments.getLength(); 164 165 // not yet initialized and acceptstring 166 if (!m_bInit && nArgs > 0 && (aArguments[0] >>= m_aAcceptString)) 167 { 168 RTL_LOGFILE_CONTEXT_TRACE1( aLog, "desktop (lo119109) Acceptor::initialize string=%s", 169 OUStringToOString(m_aAcceptString, RTL_TEXTENCODING_ASCII_US).getStr()); 170 171 // get connect string and protocol from accept string 172 // "<connectString>;<protocol>" 173 sal_Int32 nIndex1 = m_aAcceptString.indexOf( (sal_Unicode) ';' ); 174 if (nIndex1 < 0) throw IllegalArgumentException( 175 OUString::createFromAscii("Invalid accept-string format"), m_rContext, 1); 176 m_aConnectString = m_aAcceptString.copy( 0 , nIndex1 ).trim(); 177 nIndex1++; 178 sal_Int32 nIndex2 = m_aAcceptString.indexOf( (sal_Unicode) ';' , nIndex1 ); 179 if (nIndex2 < 0) nIndex2 = m_aAcceptString.getLength(); 180 m_aProtocol = m_aAcceptString.copy( nIndex1, nIndex2 - nIndex1 ); 181 182 // start accepting in new thread... 183 m_thread = osl_createThread(workerfunc, this); 184 m_bInit = sal_True; 185 bOk = sal_True; 186 } 187 188 // do we want to enable accepting? 189 sal_Bool bEnable = sal_False; 190 if (((nArgs == 1 && (aArguments[0] >>= bEnable)) || 191 (nArgs == 2 && (aArguments[1] >>= bEnable))) && 192 bEnable ) 193 { 194 m_cEnable.set(); 195 bOk = sal_True; 196 } 197 198 if (!bOk) 199 { 200 throw IllegalArgumentException( 201 OUString::createFromAscii("invalid initialization"), m_rContext, 1); 202 } 203 } 204 205 // XServiceInfo 206 const sal_Char *Acceptor::serviceName = "com.sun.star.office.Acceptor"; 207 const sal_Char *Acceptor::implementationName = "com.sun.star.office.comp.Acceptor"; 208 const sal_Char *Acceptor::supportedServiceNames[] = {"com.sun.star.office.Acceptor", NULL}; 209 OUString Acceptor::impl_getImplementationName() 210 { 211 return OUString::createFromAscii( implementationName ); 212 } 213 OUString SAL_CALL Acceptor::getImplementationName() 214 throw (RuntimeException) 215 { 216 return Acceptor::impl_getImplementationName(); 217 } 218 Sequence<OUString> Acceptor::impl_getSupportedServiceNames() 219 { 220 Sequence<OUString> aSequence; 221 for (int i=0; supportedServiceNames[i]!=NULL; i++) { 222 aSequence.realloc(i+1); 223 aSequence[i]=(OUString::createFromAscii(supportedServiceNames[i])); 224 } 225 return aSequence; 226 } 227 Sequence<OUString> SAL_CALL Acceptor::getSupportedServiceNames() 228 throw (RuntimeException) 229 { 230 return Acceptor::impl_getSupportedServiceNames(); 231 } 232 sal_Bool SAL_CALL Acceptor::supportsService( const OUString&) 233 throw (RuntimeException) 234 { 235 return sal_False; 236 } 237 238 // Factory 239 Reference< XInterface > Acceptor::impl_getInstance( const Reference< XMultiServiceFactory >& aFactory ) 240 { 241 try { 242 return (XComponent*) new Acceptor( aFactory ); 243 } catch ( Exception& ) { 244 return (XComponent*) NULL; 245 } 246 } 247 248 // InstanceProvider 249 AccInstanceProvider::AccInstanceProvider(const Reference<XMultiServiceFactory>& aFactory, const Reference<XConnection>& rConnection) 250 { 251 m_rSMgr = aFactory; 252 m_rConnection = rConnection; 253 } 254 255 AccInstanceProvider::~AccInstanceProvider() 256 { 257 } 258 259 Reference<XInterface> SAL_CALL AccInstanceProvider::getInstance (const OUString& aName ) 260 throw ( NoSuchElementException ) 261 { 262 263 Reference<XInterface> rInstance; 264 265 if ( aName.compareToAscii( "StarOffice.ServiceManager" ) == 0) 266 { 267 rInstance = Reference< XInterface >( m_rSMgr ); 268 } 269 else if(aName.compareToAscii( "StarOffice.ComponentContext" ) == 0 ) 270 { 271 rInstance = getComponentContext( m_rSMgr ); 272 } 273 else if ( aName.compareToAscii("StarOffice.NamingService" ) == 0 ) 274 { 275 Reference< XNamingService > rNamingService( 276 m_rSMgr->createInstance( OUString::createFromAscii( "com.sun.star.uno.NamingService" )), 277 UNO_QUERY ); 278 if ( rNamingService.is() ) 279 { 280 rNamingService->registerObject( 281 OUString::createFromAscii( "StarOffice.ServiceManager" ), m_rSMgr ); 282 rNamingService->registerObject( 283 OUString::createFromAscii( "StarOffice.ComponentContext" ), getComponentContext( m_rSMgr )); 284 rInstance = rNamingService; 285 } 286 } 287 /* 288 else if ( aName.compareToAscii("com.sun.star.ucb.RemoteContentProviderAcceptor" )) 289 { 290 Reference< XMultiServiceFactory > rSMgr = ::comphelper::getProcessServiceFactory(); 291 if ( rSMgr.is() ) { 292 try { 293 rInstance = rSMgr->createInstance( sObjectName ); 294 } 295 catch (Exception const &) {} 296 } 297 } 298 */ 299 return rInstance; 300 } 301 302 } 303 304 // component management stuff... 305 // ---------------------------------------------------------------------------- 306 extern "C" 307 { 308 using namespace desktop; 309 310 void SAL_CALL 311 component_getImplementationEnvironment(const sal_Char **ppEnvironmentTypeName, uno_Environment **) 312 { 313 *ppEnvironmentTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ; 314 } 315 316 void * SAL_CALL 317 component_getFactory(const sal_Char *pImplementationName, void *pServiceManager, void *) 318 { 319 void* pReturn = NULL ; 320 if ( pImplementationName && pServiceManager ) 321 { 322 // Define variables which are used in following macros. 323 Reference< XSingleServiceFactory > xFactory; 324 Reference< XMultiServiceFactory > xServiceManager( 325 reinterpret_cast< XMultiServiceFactory* >(pServiceManager)); 326 327 if (Acceptor::impl_getImplementationName().compareToAscii( pImplementationName ) == COMPARE_EQUAL ) 328 { 329 xFactory = Reference< XSingleServiceFactory >( cppu::createSingleFactory( 330 xServiceManager, Acceptor::impl_getImplementationName(), 331 Acceptor::impl_getInstance, Acceptor::impl_getSupportedServiceNames()) ); 332 } 333 334 // Factory is valid - service was found. 335 if ( xFactory.is() ) 336 { 337 xFactory->acquire(); 338 pReturn = xFactory.get(); 339 } 340 } 341 342 // Return with result of this operation. 343 return pReturn ; 344 } 345 346 } // extern "C" 347