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