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_DLLPUBLIC_EXPORT 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 SAL_DLLPUBLIC_EXPORT 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 SAL_DLLPUBLIC_EXPORT 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