| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_desktop.hxx" |
| |
| #include "acceptor.hxx" |
| #include <unotools/bootstrap.hxx> |
| #include <vos/process.hxx> |
| #include <tools/urlobj.hxx> |
| #include <tools/stream.hxx> |
| #include <vcl/svapp.hxx> |
| #include <com/sun/star/beans/XPropertySet.hpp> |
| #ifndef _COM_SUN_STAR_UNO_XNAMEINGSERVICE_HPP_ |
| #include <com/sun/star/uno/XNamingService.hpp> |
| #endif |
| |
| #include <cppuhelper/factory.hxx> |
| |
| namespace desktop |
| { |
| |
| extern "C" void workerfunc (void * acc) |
| { |
| ((Acceptor*)acc)->run(); |
| } |
| |
| static Reference<XInterface> getComponentContext( const Reference<XMultiServiceFactory>& rFactory) |
| { |
| Reference<XInterface> rContext; |
| Reference< XPropertySet > rPropSet( rFactory, UNO_QUERY ); |
| Any a = rPropSet->getPropertyValue( |
| ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ); |
| a >>= rContext; |
| return rContext; |
| } |
| |
| Mutex Acceptor::m_aMutex; |
| |
| Acceptor::Acceptor( const Reference< XMultiServiceFactory >& rFactory ) |
| : m_thread(NULL) |
| , m_aAcceptString() |
| , m_aConnectString() |
| , m_aProtocol() |
| , m_bInit(sal_False) |
| , m_bDying(false) |
| { |
| m_rSMgr = rFactory; |
| m_rAcceptor = Reference< XAcceptor > (m_rSMgr->createInstance( |
| rtl::OUString::createFromAscii( "com.sun.star.connection.Acceptor" )), |
| UNO_QUERY ); |
| m_rBridgeFactory = Reference < XBridgeFactory > (m_rSMgr->createInstance( |
| rtl::OUString::createFromAscii( "com.sun.star.bridge.BridgeFactory" )), |
| UNO_QUERY ); |
| // get component context |
| m_rContext = getComponentContext(m_rSMgr); |
| } |
| |
| |
| Acceptor::~Acceptor() |
| { |
| m_rAcceptor->stopAccepting(); |
| oslThread t; |
| { |
| osl::MutexGuard g(m_aMutex); |
| t = m_thread; |
| } |
| //prevent locking if the thread is still waiting |
| m_bDying = true; |
| m_cEnable.set(); |
| osl_joinWithThread(t); |
| { |
| // Make the final state of m_bridges visible to this thread (since |
| // m_thread is joined, the code that follows is the only one left |
| // accessing m_bridges): |
| osl::MutexGuard g(m_aMutex); |
| } |
| for (;;) { |
| com::sun::star::uno::Reference< com::sun::star::bridge::XBridge > b( |
| m_bridges.remove()); |
| if (!b.is()) { |
| break; |
| } |
| com::sun::star::uno::Reference< com::sun::star::lang::XComponent >( |
| b, com::sun::star::uno::UNO_QUERY_THROW)->dispose(); |
| } |
| } |
| |
| void SAL_CALL Acceptor::run() |
| { |
| while ( m_rAcceptor.is() && m_rBridgeFactory.is() ) |
| { |
| RTL_LOGFILE_CONTEXT( aLog, "desktop (lo119109) Acceptor::run" ); |
| try |
| { |
| // wait until we get enabled |
| RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109)"\ |
| "Acceptor::run waiting for office to come up"); |
| m_cEnable.wait(); |
| if (m_bDying) //see destructor |
| break; |
| RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109)"\ |
| "Acceptor::run now enabled and continuing"); |
| |
| // accept connection |
| Reference< XConnection > rConnection = m_rAcceptor->accept( m_aConnectString ); |
| // if we return without a valid connection we mus assume that the acceptor |
| // is destructed so we break out of the run method terminating the thread |
| if (! rConnection.is()) break; |
| OUString aDescription = rConnection->getDescription(); |
| RTL_LOGFILE_CONTEXT_TRACE1( aLog, "desktop (lo119109) Acceptor::run connection %s", |
| OUStringToOString(aDescription, RTL_TEXTENCODING_ASCII_US).getStr()); |
| |
| // create instanceprovider for this connection |
| Reference< XInstanceProvider > rInstanceProvider( |
| (XInstanceProvider*)new AccInstanceProvider(m_rSMgr, rConnection)); |
| // create the bridge. The remote end will have a reference to this bridge |
| // thus preventing the bridge from being disposed. When the remote end releases |
| // the bridge, it will be destructed. |
| Reference< XBridge > rBridge = m_rBridgeFactory->createBridge( |
| rtl::OUString() ,m_aProtocol ,rConnection ,rInstanceProvider ); |
| osl::MutexGuard g(m_aMutex); |
| m_bridges.add(rBridge); |
| } catch (Exception&) { |
| // connection failed... |
| // something went wrong during connection setup. |
| // just wait for a new connection to accept |
| } |
| } |
| } |
| |
| // XInitialize |
| void SAL_CALL Acceptor::initialize( const Sequence<Any>& aArguments ) |
| throw( Exception ) |
| { |
| // prevent multiple initialization |
| ClearableMutexGuard aGuard( m_aMutex ); |
| RTL_LOGFILE_CONTEXT( aLog, "destop (lo119109) Acceptor::initialize()" ); |
| |
| sal_Bool bOk = sal_False; |
| |
| // arg count |
| int nArgs = aArguments.getLength(); |
| |
| // not yet initialized and acceptstring |
| if (!m_bInit && nArgs > 0 && (aArguments[0] >>= m_aAcceptString)) |
| { |
| RTL_LOGFILE_CONTEXT_TRACE1( aLog, "desktop (lo119109) Acceptor::initialize string=%s", |
| OUStringToOString(m_aAcceptString, RTL_TEXTENCODING_ASCII_US).getStr()); |
| |
| // get connect string and protocol from accept string |
| // "<connectString>;<protocol>" |
| sal_Int32 nIndex1 = m_aAcceptString.indexOf( (sal_Unicode) ';' ); |
| if (nIndex1 < 0) throw IllegalArgumentException( |
| OUString::createFromAscii("Invalid accept-string format"), m_rContext, 1); |
| m_aConnectString = m_aAcceptString.copy( 0 , nIndex1 ).trim(); |
| nIndex1++; |
| sal_Int32 nIndex2 = m_aAcceptString.indexOf( (sal_Unicode) ';' , nIndex1 ); |
| if (nIndex2 < 0) nIndex2 = m_aAcceptString.getLength(); |
| m_aProtocol = m_aAcceptString.copy( nIndex1, nIndex2 - nIndex1 ); |
| |
| // start accepting in new thread... |
| m_thread = osl_createThread(workerfunc, this); |
| m_bInit = sal_True; |
| bOk = sal_True; |
| } |
| |
| // do we want to enable accepting? |
| sal_Bool bEnable = sal_False; |
| if (((nArgs == 1 && (aArguments[0] >>= bEnable)) || |
| (nArgs == 2 && (aArguments[1] >>= bEnable))) && |
| bEnable ) |
| { |
| m_cEnable.set(); |
| bOk = sal_True; |
| } |
| |
| if (!bOk) |
| { |
| throw IllegalArgumentException( |
| OUString::createFromAscii("invalid initialization"), m_rContext, 1); |
| } |
| } |
| |
| // XServiceInfo |
| const sal_Char *Acceptor::serviceName = "com.sun.star.office.Acceptor"; |
| const sal_Char *Acceptor::implementationName = "com.sun.star.office.comp.Acceptor"; |
| const sal_Char *Acceptor::supportedServiceNames[] = {"com.sun.star.office.Acceptor", NULL}; |
| OUString Acceptor::impl_getImplementationName() |
| { |
| return OUString::createFromAscii( implementationName ); |
| } |
| OUString SAL_CALL Acceptor::getImplementationName() |
| throw (RuntimeException) |
| { |
| return Acceptor::impl_getImplementationName(); |
| } |
| Sequence<OUString> Acceptor::impl_getSupportedServiceNames() |
| { |
| Sequence<OUString> aSequence; |
| for (int i=0; supportedServiceNames[i]!=NULL; i++) { |
| aSequence.realloc(i+1); |
| aSequence[i]=(OUString::createFromAscii(supportedServiceNames[i])); |
| } |
| return aSequence; |
| } |
| Sequence<OUString> SAL_CALL Acceptor::getSupportedServiceNames() |
| throw (RuntimeException) |
| { |
| return Acceptor::impl_getSupportedServiceNames(); |
| } |
| sal_Bool SAL_CALL Acceptor::supportsService( const OUString&) |
| throw (RuntimeException) |
| { |
| return sal_False; |
| } |
| |
| // Factory |
| Reference< XInterface > Acceptor::impl_getInstance( const Reference< XMultiServiceFactory >& aFactory ) |
| { |
| try { |
| return (XComponent*) new Acceptor( aFactory ); |
| } catch ( Exception& ) { |
| return (XComponent*) NULL; |
| } |
| } |
| |
| // InstanceProvider |
| AccInstanceProvider::AccInstanceProvider(const Reference<XMultiServiceFactory>& aFactory, const Reference<XConnection>& rConnection) |
| { |
| m_rSMgr = aFactory; |
| m_rConnection = rConnection; |
| } |
| |
| AccInstanceProvider::~AccInstanceProvider() |
| { |
| } |
| |
| Reference<XInterface> SAL_CALL AccInstanceProvider::getInstance (const OUString& aName ) |
| throw ( NoSuchElementException ) |
| { |
| |
| Reference<XInterface> rInstance; |
| |
| if ( aName.compareToAscii( "StarOffice.ServiceManager" ) == 0) |
| { |
| rInstance = Reference< XInterface >( m_rSMgr ); |
| } |
| else if(aName.compareToAscii( "StarOffice.ComponentContext" ) == 0 ) |
| { |
| rInstance = getComponentContext( m_rSMgr ); |
| } |
| else if ( aName.compareToAscii("StarOffice.NamingService" ) == 0 ) |
| { |
| Reference< XNamingService > rNamingService( |
| m_rSMgr->createInstance( OUString::createFromAscii( "com.sun.star.uno.NamingService" )), |
| UNO_QUERY ); |
| if ( rNamingService.is() ) |
| { |
| rNamingService->registerObject( |
| OUString::createFromAscii( "StarOffice.ServiceManager" ), m_rSMgr ); |
| rNamingService->registerObject( |
| OUString::createFromAscii( "StarOffice.ComponentContext" ), getComponentContext( m_rSMgr )); |
| rInstance = rNamingService; |
| } |
| } |
| /* |
| else if ( aName.compareToAscii("com.sun.star.ucb.RemoteContentProviderAcceptor" )) |
| { |
| Reference< XMultiServiceFactory > rSMgr = ::comphelper::getProcessServiceFactory(); |
| if ( rSMgr.is() ) { |
| try { |
| rInstance = rSMgr->createInstance( sObjectName ); |
| } |
| catch (Exception const &) {} |
| } |
| } |
| */ |
| return rInstance; |
| } |
| |
| } |
| |
| // component management stuff... |
| // ---------------------------------------------------------------------------- |
| extern "C" |
| { |
| using namespace desktop; |
| |
| void SAL_CALL |
| component_getImplementationEnvironment(const sal_Char **ppEnvironmentTypeName, uno_Environment **) |
| { |
| *ppEnvironmentTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ; |
| } |
| |
| void * SAL_CALL |
| component_getFactory(const sal_Char *pImplementationName, void *pServiceManager, void *) |
| { |
| void* pReturn = NULL ; |
| if ( pImplementationName && pServiceManager ) |
| { |
| // Define variables which are used in following macros. |
| Reference< XSingleServiceFactory > xFactory; |
| Reference< XMultiServiceFactory > xServiceManager( |
| reinterpret_cast< XMultiServiceFactory* >(pServiceManager)); |
| |
| if (Acceptor::impl_getImplementationName().compareToAscii( pImplementationName ) == COMPARE_EQUAL ) |
| { |
| xFactory = Reference< XSingleServiceFactory >( cppu::createSingleFactory( |
| xServiceManager, Acceptor::impl_getImplementationName(), |
| Acceptor::impl_getInstance, Acceptor::impl_getSupportedServiceNames()) ); |
| } |
| |
| // Factory is valid - service was found. |
| if ( xFactory.is() ) |
| { |
| xFactory->acquire(); |
| pReturn = xFactory.get(); |
| } |
| } |
| |
| // Return with result of this operation. |
| return pReturn ; |
| } |
| |
| } // extern "C" |