xref: /aoo41x/main/io/source/acceptor/acceptor.cxx (revision cdf0e10c)
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