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