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