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