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 { 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 { 215 return Acceptor::impl_getImplementationName(); 216 } 217 Sequence<OUString> Acceptor::impl_getSupportedServiceNames() 218 { 219 Sequence<OUString> aSequence; 220 for (int i=0; supportedServiceNames[i]!=NULL; i++) { 221 aSequence.realloc(i+1); 222 aSequence[i]=(OUString::createFromAscii(supportedServiceNames[i])); 223 } 224 return aSequence; 225 } 226 Sequence<OUString> SAL_CALL Acceptor::getSupportedServiceNames() 227 { 228 return Acceptor::impl_getSupportedServiceNames(); 229 } 230 sal_Bool SAL_CALL Acceptor::supportsService( const OUString&) 231 { 232 return sal_False; 233 } 234 235 // Factory 236 Reference< XInterface > Acceptor::impl_getInstance( const Reference< XMultiServiceFactory >& aFactory ) 237 { 238 try { 239 return (XComponent*) new Acceptor( aFactory ); 240 } catch ( Exception& ) { 241 return (XComponent*) NULL; 242 } 243 } 244 245 // InstanceProvider 246 AccInstanceProvider::AccInstanceProvider(const Reference<XMultiServiceFactory>& aFactory, const Reference<XConnection>& rConnection) 247 { 248 m_rSMgr = aFactory; 249 m_rConnection = rConnection; 250 } 251 252 AccInstanceProvider::~AccInstanceProvider() 253 { 254 } 255 256 Reference<XInterface> SAL_CALL AccInstanceProvider::getInstance (const OUString& aName ) 257 { 258 259 Reference<XInterface> rInstance; 260 261 if ( aName.compareToAscii( "StarOffice.ServiceManager" ) == 0) 262 { 263 rInstance = Reference< XInterface >( m_rSMgr ); 264 } 265 else if(aName.compareToAscii( "StarOffice.ComponentContext" ) == 0 ) 266 { 267 rInstance = getComponentContext( m_rSMgr ); 268 } 269 else if ( aName.compareToAscii("StarOffice.NamingService" ) == 0 ) 270 { 271 Reference< XNamingService > rNamingService( 272 m_rSMgr->createInstance( OUString::createFromAscii( "com.sun.star.uno.NamingService" )), 273 UNO_QUERY ); 274 if ( rNamingService.is() ) 275 { 276 rNamingService->registerObject( 277 OUString::createFromAscii( "StarOffice.ServiceManager" ), m_rSMgr ); 278 rNamingService->registerObject( 279 OUString::createFromAscii( "StarOffice.ComponentContext" ), getComponentContext( m_rSMgr )); 280 rInstance = rNamingService; 281 } 282 } 283 /* 284 else if ( aName.compareToAscii("com.sun.star.ucb.RemoteContentProviderAcceptor" )) 285 { 286 Reference< XMultiServiceFactory > rSMgr = ::comphelper::getProcessServiceFactory(); 287 if ( rSMgr.is() ) { 288 try { 289 rInstance = rSMgr->createInstance( sObjectName ); 290 } 291 catch (Exception const &) {} 292 } 293 } 294 */ 295 return rInstance; 296 } 297 298 } 299 300 // component management stuff... 301 // ---------------------------------------------------------------------------- 302 extern "C" 303 { 304 using namespace desktop; 305 306 void SAL_CALL 307 component_getImplementationEnvironment(const sal_Char **ppEnvironmentTypeName, uno_Environment **) 308 { 309 *ppEnvironmentTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ; 310 } 311 312 void * SAL_CALL 313 component_getFactory(const sal_Char *pImplementationName, void *pServiceManager, void *) 314 { 315 void* pReturn = NULL ; 316 if ( pImplementationName && pServiceManager ) 317 { 318 // Define variables which are used in following macros. 319 Reference< XSingleServiceFactory > xFactory; 320 Reference< XMultiServiceFactory > xServiceManager( 321 reinterpret_cast< XMultiServiceFactory* >(pServiceManager)); 322 323 if (Acceptor::impl_getImplementationName().compareToAscii( pImplementationName ) == COMPARE_EQUAL ) 324 { 325 xFactory = Reference< XSingleServiceFactory >( cppu::createSingleFactory( 326 xServiceManager, Acceptor::impl_getImplementationName(), 327 Acceptor::impl_getInstance, Acceptor::impl_getSupportedServiceNames()) ); 328 } 329 330 // Factory is valid - service was found. 331 if ( xFactory.is() ) 332 { 333 xFactory->acquire(); 334 pReturn = xFactory.get(); 335 } 336 } 337 338 // Return with result of this operation. 339 return pReturn ; 340 } 341 342 } // extern "C" 343