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