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