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