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_io.hxx" 30 #include <osl/mutex.hxx> 31 32 #include <uno/mapping.hxx> 33 34 #include <cppuhelper/factory.hxx> 35 #include <cppuhelper/implbase2.hxx> 36 #include <cppuhelper/implementationentry.hxx> 37 #include "cppuhelper/unourl.hxx" 38 #include "rtl/malformeduriexception.hxx" 39 40 #include <com/sun/star/connection/XAcceptor.hpp> 41 #include <com/sun/star/lang/XServiceInfo.hpp> 42 43 #include "acceptor.hxx" 44 45 #define IMPLEMENTATION_NAME "com.sun.star.comp.io.Acceptor" 46 #define SERVICE_NAME "com.sun.star.connection.Acceptor" 47 48 using namespace ::osl; 49 using namespace ::rtl; 50 using namespace ::cppu; 51 using namespace ::com::sun::star::uno; 52 using namespace ::com::sun::star::lang; 53 using namespace ::com::sun::star::registry; 54 using namespace ::com::sun::star::connection; 55 56 namespace io_acceptor 57 { 58 rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT; 59 60 class OAcceptor : public WeakImplHelper2< XAcceptor, XServiceInfo > 61 { 62 public: 63 OAcceptor(const Reference< XComponentContext > & xCtx); 64 virtual ~OAcceptor(); 65 public: 66 // Methods 67 virtual Reference< XConnection > SAL_CALL accept( const OUString& sConnectionDescription ) 68 throw( AlreadyAcceptingException, 69 ConnectionSetupException, 70 IllegalArgumentException, 71 RuntimeException); 72 virtual void SAL_CALL stopAccepting( ) throw( RuntimeException); 73 74 public: // XServiceInfo 75 virtual OUString SAL_CALL getImplementationName() throw(); 76 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw(); 77 virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw(); 78 79 private: 80 PipeAcceptor *m_pPipe; 81 SocketAcceptor *m_pSocket; 82 Mutex m_mutex; 83 OUString m_sLastDescription; 84 sal_Bool m_bInAccept; 85 86 Reference< XMultiComponentFactory > _xSMgr; 87 Reference< XComponentContext > _xCtx; 88 Reference<XAcceptor> _xAcceptor; 89 }; 90 91 92 OAcceptor::OAcceptor( const Reference< XComponentContext > & xCtx ) 93 : m_pPipe( 0 ) 94 , m_pSocket( 0 ) 95 , m_bInAccept( sal_False ) 96 , _xSMgr( xCtx->getServiceManager() ) 97 , _xCtx( xCtx ) 98 { 99 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); 100 } 101 102 OAcceptor::~OAcceptor() 103 { 104 if( m_pPipe ) 105 { 106 delete m_pPipe; 107 } 108 if( m_pSocket ) 109 { 110 delete m_pSocket; 111 } 112 g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); 113 } 114 115 struct BeingInAccept 116 { 117 BeingInAccept( sal_Bool *pFlag,const OUString & sConnectionDescription ) throw( AlreadyAcceptingException) 118 : m_pFlag( pFlag ) 119 { 120 if( *m_pFlag ) 121 { 122 OUString sMessage( RTL_CONSTASCII_USTRINGPARAM( "AlreadyAcceptingException :" ) ); 123 sMessage += sConnectionDescription; 124 throw AlreadyAcceptingException( sMessage , Reference< XInterface > () ); 125 } 126 *m_pFlag = sal_True; 127 } 128 ~BeingInAccept() 129 { 130 *m_pFlag = sal_False; 131 } 132 sal_Bool *m_pFlag; 133 }; 134 135 Reference< XConnection > OAcceptor::accept( const OUString &sConnectionDescription ) 136 throw( AlreadyAcceptingException, 137 ConnectionSetupException, 138 IllegalArgumentException, 139 RuntimeException) 140 { 141 OSL_TRACE( 142 "acceptor %s\n", 143 OUStringToOString( 144 sConnectionDescription, RTL_TEXTENCODING_ASCII_US).getStr()); 145 // if there is a thread alread accepting in this object, throw an exception. 146 struct BeingInAccept guard( &m_bInAccept, sConnectionDescription ); 147 148 Reference< XConnection > r; 149 if( m_sLastDescription.getLength() && 150 m_sLastDescription != sConnectionDescription ) 151 { 152 // instantiate another acceptor for different ports 153 OUString sMessage = OUString( RTL_CONSTASCII_USTRINGPARAM( 154 "acceptor::accept called multiple times with different conncetion strings\n" ) ); 155 throw ConnectionSetupException( sMessage, Reference< XInterface > () ); 156 } 157 158 if( ! m_sLastDescription.getLength() ) 159 { 160 // setup the acceptor 161 try 162 { 163 cppu::UnoUrlDescriptor aDesc(sConnectionDescription); 164 if (aDesc.getName().equalsAsciiL( 165 RTL_CONSTASCII_STRINGPARAM("pipe"))) 166 { 167 rtl::OUString aName( 168 aDesc.getParameter( 169 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 170 "name")))); 171 172 m_pPipe = new PipeAcceptor(aName, sConnectionDescription); 173 174 try 175 { 176 m_pPipe->init(); 177 } 178 catch( ... ) 179 { 180 { 181 MutexGuard g( m_mutex ); 182 delete m_pPipe; 183 m_pPipe = 0; 184 } 185 throw; 186 } 187 } 188 else if (aDesc.getName().equalsAsciiL( 189 RTL_CONSTASCII_STRINGPARAM("socket"))) 190 { 191 rtl::OUString aHost; 192 if (aDesc.hasParameter( 193 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("host")))) 194 aHost = aDesc.getParameter( 195 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("host"))); 196 else 197 aHost = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 198 "localhost")); 199 sal_uInt16 nPort = static_cast< sal_uInt16 >( 200 aDesc.getParameter( 201 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("port"))). 202 toInt32()); 203 bool bTcpNoDelay 204 = aDesc.getParameter( 205 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( 206 "tcpnodelay"))).toInt32() != 0; 207 208 m_pSocket = new SocketAcceptor( 209 aHost, nPort, bTcpNoDelay, sConnectionDescription); 210 211 try 212 { 213 m_pSocket->init(); 214 } 215 catch( ... ) 216 { 217 { 218 MutexGuard g( m_mutex ); 219 delete m_pSocket; 220 m_pSocket = 0; 221 } 222 throw; 223 } 224 } 225 else 226 { 227 OUString delegatee = OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.connection.Acceptor.")); 228 delegatee += aDesc.getName(); 229 230 OSL_TRACE( 231 "trying to get service %s\n", 232 OUStringToOString( 233 delegatee, RTL_TEXTENCODING_ASCII_US).getStr()); 234 _xAcceptor = Reference<XAcceptor>( 235 _xSMgr->createInstanceWithContext(delegatee, _xCtx), UNO_QUERY); 236 237 if(!_xAcceptor.is()) 238 { 239 OUString message(RTL_CONSTASCII_USTRINGPARAM("Acceptor: unknown delegatee ")); 240 message += delegatee; 241 242 throw ConnectionSetupException(message, Reference<XInterface>()); 243 } 244 } 245 } 246 catch (rtl::MalformedUriException & rEx) 247 { 248 throw IllegalArgumentException( 249 rEx.getMessage(), 250 Reference< XInterface > (), 251 0 ); 252 } 253 m_sLastDescription = sConnectionDescription; 254 } 255 256 if( m_pPipe ) 257 { 258 r = m_pPipe->accept(); 259 } 260 else if( m_pSocket ) 261 { 262 r = m_pSocket->accept(); 263 } 264 else 265 { 266 r = _xAcceptor->accept(sConnectionDescription); 267 } 268 269 return r; 270 } 271 272 void SAL_CALL OAcceptor::stopAccepting( ) throw( RuntimeException) 273 { 274 MutexGuard guard( m_mutex ); 275 276 if( m_pPipe ) 277 { 278 m_pPipe->stopAccepting(); 279 } 280 else if ( m_pSocket ) 281 { 282 m_pSocket->stopAccepting(); 283 } 284 else if( _xAcceptor.is() ) 285 { 286 _xAcceptor->stopAccepting(); 287 } 288 289 } 290 291 OUString acceptor_getImplementationName() 292 { 293 return OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) ); 294 } 295 296 Reference< XInterface > SAL_CALL acceptor_CreateInstance( const Reference< XComponentContext > & xCtx) 297 { 298 return Reference < XInterface >( ( OWeakObject * ) new OAcceptor(xCtx) ); 299 } 300 301 Sequence< OUString > acceptor_getSupportedServiceNames() 302 { 303 static Sequence < OUString > *pNames = 0; 304 if( ! pNames ) 305 { 306 MutexGuard guard( Mutex::getGlobalMutex() ); 307 if( !pNames ) 308 { 309 static Sequence< OUString > seqNames(1); 310 seqNames.getArray()[0] = OUString::createFromAscii( SERVICE_NAME ); 311 pNames = &seqNames; 312 } 313 } 314 return *pNames; 315 } 316 317 OUString OAcceptor::getImplementationName() throw() 318 { 319 return acceptor_getImplementationName(); 320 } 321 322 sal_Bool OAcceptor::supportsService(const OUString& ServiceName) throw() 323 { 324 Sequence< OUString > aSNL = getSupportedServiceNames(); 325 const OUString * pArray = aSNL.getConstArray(); 326 327 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) 328 if( pArray[i] == ServiceName ) 329 return sal_True; 330 331 return sal_False; 332 } 333 334 Sequence< OUString > OAcceptor::getSupportedServiceNames(void) throw() 335 { 336 return acceptor_getSupportedServiceNames(); 337 } 338 339 340 } 341 342 using namespace io_acceptor; 343 344 static struct ImplementationEntry g_entries[] = 345 { 346 { 347 acceptor_CreateInstance, acceptor_getImplementationName , 348 acceptor_getSupportedServiceNames, createSingleComponentFactory , 349 &g_moduleCount.modCnt , 0 350 }, 351 { 0, 0, 0, 0, 0, 0 } 352 }; 353 354 extern "C" 355 { 356 357 sal_Bool SAL_CALL component_canUnload( TimeValue *pTime ) 358 { 359 return g_moduleCount.canUnload( &g_moduleCount , pTime ); 360 } 361 362 //================================================================================================== 363 void SAL_CALL component_getImplementationEnvironment( 364 const sal_Char ** ppEnvTypeName, uno_Environment ** ) 365 { 366 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; 367 } 368 //================================================================================================== 369 void * SAL_CALL component_getFactory( 370 const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey ) 371 { 372 return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries ); 373 } 374 } 375 376 377 378