<commit_before>/*************************************************************************
 *
 *  $RCSfile: backendfactory.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: hr $ $Date: 2003-03-19 16:18:46 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "backendfactory.hxx"

#ifndef CONFIGMGR_API_FACTORY_HXX_
#include "confapifactory.hxx"
#endif
#ifndef CONFIGMGR_BOOTSTRAPCONTEXT_HXX_
#include "bootstrapcontext.hxx"
#endif
#ifndef CONFIGMGR_BOOTSTRAP_HXX_
#include "bootstrap.hxx"
#endif
#ifndef CONFIGMGR_BACKEND_BACKENDACCESS_HXX_
#include "backendaccess.hxx"
#endif
#ifndef CONFIGMGR_SERVICEINFOHELPER_HXX_
#include "serviceinfohelper.hxx"
#endif
#ifndef CONFIGMGR_WRAPEXCEPTION_HXX
#include "wrapexception.hxx"
#endif

#ifndef _COM_SUN_STAR_CONFIGURATION_CANNOTLOADCONFIGURATIONEXCEPTION_HPP_
#include <com/sun/star/configuration/CannotLoadConfigurationException.hpp>
#endif

#include <drafts/com/sun/star/configuration/backend/XBackend.hpp>
#include <drafts/com/sun/star/configuration/backend/XSingleBackend.hpp>

namespace configmgr
{
// -------------------------------------------------------------------------
    namespace backend
    {
// -------------------------------------------------------------------------
        namespace uno = ::com::sun::star::uno;
        namespace lang = ::com::sun::star::lang;
        namespace backenduno = drafts::com::sun::star::configuration::backend;
// -------------------------------------------------------------------------
const sal_Char k_DefaultBackendWrapper[] = "com.sun.star.comp.configuration.backend.SingleBackendAdapter";
const sal_Char k_DefaultBackendService[] = "com.sun.star.comp.configuration.backend.LocalSingleBackend";

// -------------------------------------------------------------------------
const sal_Char k_DefaultBackendServiceAndImplName[]         = K_DefaultBackendServiceAndImplName ;
const sal_Char k_DefaultSingleBackendServiceAndImplName[]   = K_DefaultSingleBackendServiceAndImplName ;

// -------------------------------------------------------------------------
const sal_Char k_GenericBackendServiceAndImplName[]         = "com.sun.star.configuration.backend.Backend" ;
const sal_Char k_GenericSingleBackendServiceAndImplName[]   = "com.sun.star.configuration.backend.SingleBackend" ;

// -------------------------------------------------------------------------
static AsciiServiceName const k_BackendServiceNames [] =
{
    k_DefaultBackendServiceAndImplName,
    k_GenericBackendServiceAndImplName,
    0
};
static AsciiServiceName const k_SingleBackendServiceNames [] =
{
    k_DefaultSingleBackendServiceAndImplName,
    k_GenericSingleBackendServiceAndImplName,
    0
};
// -------------------------------------------------------------------------
static const ServiceRegistrationInfo k_DefaultBackendServiceInfo =
{
    k_DefaultBackendServiceAndImplName,
    k_BackendServiceNames
};
static const ServiceRegistrationInfo k_DefaultSingleBackendServiceInfo =
{
    k_DefaultSingleBackendServiceAndImplName,
    k_SingleBackendServiceNames
};
// -------------------------------------------------------------------------
static const ServiceRegistrationInfo k_GenericBackendServiceInfo =
{
    k_GenericBackendServiceAndImplName,
    k_BackendServiceNames + 1
};
static const ServiceRegistrationInfo k_GenericSingleBackendServiceInfo =
{
    k_GenericSingleBackendServiceAndImplName,
    k_SingleBackendServiceNames + 1
};
// -------------------------------------------------------------------------
static const SingletonRegistrationInfo k_DefaultBackendSingletonInfo =
{
    K_DefaultBackendSingletonName,
    k_DefaultBackendServiceAndImplName,
    k_DefaultBackendServiceAndImplName,
    & k_GenericBackendServiceInfo
};
static const SingletonRegistrationInfo k_DefaultSingleBackendSingletonInfo =
{
    K_DefaultSingleBackendSingletonName,
    k_DefaultSingleBackendServiceAndImplName,
    k_DefaultSingleBackendServiceAndImplName,
    & k_GenericSingleBackendServiceInfo
};
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
const SingletonRegistrationInfo * getDefaultBackendSingletonInfo()
{
    return & k_DefaultBackendSingletonInfo;
}
// -------------------------------------------------------------------------
const SingletonRegistrationInfo * getDefaultSingleBackendSingletonInfo()
{
    return & k_DefaultSingleBackendSingletonInfo;
}
// -------------------------------------------------------------------------

const ServiceRegistrationInfo   * getDefaultBackendServiceInfo()
{
    return & k_DefaultBackendServiceInfo;
}
// -------------------------------------------------------------------------
const ServiceRegistrationInfo   * getDefaultSingleBackendServiceInfo()
{
    return & k_DefaultSingleBackendServiceInfo;
}
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------

uno::Reference<uno::XInterface> SAL_CALL
    getDefaultBackendSingleton( CreationContext const& xContext )
{
    OSL_ENSURE( xContext.is(), "ERROR: NULL context has no singletons" );

    UnoContextTunnel aTunnel;
    aTunnel.passthru( xContext );

    uno::Reference<uno::XInterface> xResult;

    if (xContext.is())
    try
    {
        xContext->getValueByName(SINGLETON(K_DefaultBackendSingletonName))
            >>= xResult;
    }
    catch (uno::Exception & )
    {
        // to do: really use the tunneled failure when that is set properly
        if ( aTunnel.recoverFailure(true).hasValue() )
        {
            // have a failure, but can't recover it
            // -> try to regenerate
            instantiateDefaultBackend(xContext);

            OSL_ENSURE(false, "Cannot recreate configuration backend instantiation failure - using generic error");
        }
        // cannot recover any failure
        throw;
    }

    return xResult;
}
// -------------------------------------------------------------------------

uno::Reference<uno::XInterface> SAL_CALL
    getDefaultSingleBackendSingleton( CreationContext const& xContext )
{
    OSL_ENSURE( xContext.is(), "ERROR: NULL context has no singletons" );

    UnoContextTunnel aTunnel;
    aTunnel.passthru( xContext );

    uno::Reference<uno::XInterface> xResult;

    if (xContext.is())
    try
    {
        xContext->getValueByName(SINGLETON(K_DefaultSingleBackendSingletonName))
            >>= xResult;
    }
    catch (uno::Exception & )
    {
        // to do: really use the tunneled failure when that is set properly
        if ( aTunnel.recoverFailure(true).hasValue() )
        {
            // have a failure, but can't recover it
            // -> try to regenerate
            instantiateDefaultSingleBackend(xContext);

            OSL_ENSURE(false, "Cannot recreate configuration backend instantiation failure - using generic error");
        }
        // cannot recover any failure
        throw;
    }

    return xResult;
}
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------

typedef BackendFactory::CreationContext CreationContext;
typedef uno::Sequence< uno::Any >       UnoInitArgs;
// -------------------------------------------------------------------------

static
UnoInitArgs createInitArgs(ContextReader const & _aContext)
{
    OSL_ASSERT(_aContext.hasBootstrapContext());
    uno::Sequence< uno::Any > aResult( 1 );
    aResult[0] <<= _aContext.getBootstrapContext();
    return aResult;
}
// -------------------------------------------------------------------------

static
inline
uno::Reference< uno::XInterface > createService(ContextReader const & _aCtx, UnoInitArgs const & _aInitArgs, OUString const & _aSvc)
{
    uno::Reference< lang::XMultiComponentFactory > xFactory = _aCtx.getServiceManager();
    OSL_ENSURE(xFactory.is(),"ERROR: ComponentContext has no service manager\n");
    if (!xFactory.is()) throw uno::RuntimeException( OUString::createFromAscii("ERROR: ComponentContext has no service manager\n"), NULL );
    return xFactory->createInstanceWithArgumentsAndContext( _aSvc, _aInitArgs, _aCtx.getBaseContext());
}
// -------------------------------------------------------------------------

typedef uno::Reference< backenduno::XSingleBackend >    UnoSingleBackend;
typedef uno::Reference< backenduno::XBackend >          UnoBackend;

static
UnoBackend wrapSingleBackend(ContextReader const & _aSettings, UnoInitArgs const & _aInitArgs, UnoSingleBackend const & _xWrappedBackend)
{
    OSL_ASSERT(_aSettings.hasUnoBackendWrapper() || _aSettings.hasBootstrapContext());

    OUString aWrapperSvc = _aSettings.hasUnoBackendWrapper() ?
                                _aSettings.getUnoBackendWrapper() :
                                OUString::createFromAscii(k_DefaultBackendWrapper);

    OSL_ENSURE (aWrapperSvc.getLength(), "ERROR: No wrapper service for wrapped configuration");
    OSL_ENSURE (_xWrappedBackend.is(), "ERROR: No backend to wrap for wrapped configuration");

    sal_Int32 const nBaseArgsCount = _aInitArgs.getLength();
    UnoInitArgs aExtendedArgs( _aInitArgs );
    aExtendedArgs.realloc( nBaseArgsCount + 1 );
    aExtendedArgs[nBaseArgsCount] <<= _xWrappedBackend;

    return UnoBackend::query( createService(_aSettings,aExtendedArgs,aWrapperSvc) );
}
// -------------------------------------------------------------------------

static
UnoBackend createOfflineBackend(ContextReader const & _aSettings, UnoInitArgs const & _aInitArgs)
{
    OSL_ASSERT(_aSettings.hasUnoBackendWrapper() || _aSettings.hasBootstrapContext());

    UnoBackend xResult;
    if ( _aSettings.hasUnoBackendWrapper() )
    {
        OUString const aWrapperSvc = _aSettings.getUnoBackendWrapper();

        xResult = UnoBackend::query( createService(_aSettings,_aInitArgs,aWrapperSvc) );
    }

    return xResult;
}
// -------------------------------------------------------------------------

static
uno::Reference< uno::XInterface > createRealBackend(ContextReader const & _aSettings, UnoInitArgs const & _aInitArgs)
{
    OSL_ASSERT(_aSettings.hasUnoBackendService() || _aSettings.hasBootstrapContext());

    OUString const aBackendServiceName = _aSettings.hasUnoBackendService() ?
                                        _aSettings.getUnoBackendService() :
                                        OUString::createFromAscii(k_DefaultBackendService);

    uno::Reference< uno::XInterface > xResult =
        createService(_aSettings,_aInitArgs,aBackendServiceName);

    return xResult;
}
// -------------------------------------------------------------------------

static
UnoBackend createOnlineBackend(ContextReader const & _aSettings, UnoInitArgs const & _aInitArgs)
{
    OSL_ENSURE( _aSettings.isUnoBackend(), "ERROR - BackendFactory: For legacy backends use createSessionBackend()");

    UnoBackend xResult;

    uno::Reference< uno::XInterface > xRealBackend = createRealBackend(_aSettings,_aInitArgs);

    if (_aSettings.hasUnoBackendWrapper())
    {
        // try wrapping a single backend
        UnoSingleBackend xSingleRealBackend( xRealBackend, uno::UNO_QUERY);
        if (xSingleRealBackend.is())
            xResult = wrapSingleBackend(_aSettings,_aInitArgs,xSingleRealBackend);

        // if we don't have one, try using it as unwrapped backend
        else
            xResult.set(xRealBackend, uno::UNO_QUERY);
    }
    else
    {
         // look for a direct implementation of XBackend
        xResult.set(xRealBackend, uno::UNO_QUERY);
        if (!xResult.is())
        {
            // try the default wrapper if we only have a single backend
            UnoSingleBackend xSingleRealBackend( xRealBackend, uno::UNO_QUERY);
            if (xSingleRealBackend.is())
                xResult = wrapSingleBackend(_aSettings,_aInitArgs,xSingleRealBackend);

            else
                OSL_ENSURE( !xRealBackend.is(), "Configuration Backend implements no known backend interface" );
        }
    }

    return xResult;
}
// -------------------------------------------------------------------------

static UnoBackend createUnoBackend(CreationContext const& _xCtx)
{
    ContextReader aSettings(_xCtx);
    OSL_ENSURE( aSettings.isUnoBackend(), "ERROR - BackendFactory: Legacy backends are not supported any more");

    UnoInitArgs aArguments = createInitArgs(aSettings);

    sal_Bool bOffline = aSettings.hasOfflineSetting() ? aSettings.getOfflineSetting() : !aSettings.hasUnoBackendService();

    UnoBackend xResult;

    if (!bOffline)
        xResult = createOnlineBackend (aSettings,aArguments);

    if (!xResult.is())
        xResult = createOfflineBackend(aSettings,aArguments);

    return xResult;
}
// -------------------------------------------------------------------------
// to do: tunnel and raise fully typed exception information (and use it in the get..Singleton wrappers)
    #define TUNNEL_ALL_EXCEPTIONS()     \
        WRAP_CONFIGBACKEND_CREATION_EXCEPTIONS1( UnoContextTunnel::tunnelFailure, true )

// -------------------------------------------------------------------------

uno::Reference<uno::XInterface> SAL_CALL instantiateDefaultBackend( CreationContext const& xTargetContext )
{
    CreationContext xContext = UnoContextTunnel::recoverContext(xTargetContext);

    try
    {
        return createUnoBackend(xContext);
    }
    TUNNEL_ALL_EXCEPTIONS()
}
// -------------------------------------------------------------------------
uno::Reference<uno::XInterface> SAL_CALL instantiateDefaultSingleBackend( CreationContext const& xTargetContext )
{
    CreationContext xContext = UnoContextTunnel::recoverContext(xTargetContext);

    ContextReader aSettings( xContext );

    UnoInitArgs aArguments = createInitArgs(aSettings);

    try
    {
        return createRealBackend(aSettings,aArguments);
    }
    TUNNEL_ALL_EXCEPTIONS()
}

// -------------------------------------------------------------------------

UnoBackend BackendFactory::getUnoBackend()
{
    return UnoBackend::query( getDefaultBackendSingleton(m_xCtx) );
}
// -------------------------------------------------------------------------

rtl::Reference<IMergedDataProvider> BackendFactory::createBackend()
{
    rtl::Reference< IMergedDataProvider > xBackend;

    UnoBackend xBackendService = this->getUnoBackend();

    if (xBackendService.is())
        xBackend = new BackendAccess(xBackendService, m_xCtx);

    return xBackend;
}
// -------------------------------------------------------------------------

BackendFactory BackendFactory::instance(CreationContext const & _xCtx)
{
    return BackendFactory(_xCtx);
}

//-----------------------------------------------------------------------------
    } // namespace
//-----------------------------------------------------------------------------
} // namespace
<commit_msg>INTEGRATION: CWS configapi01 (1.7.10); FILE MERGED 2003/04/10 15:47:00 jb 1.7.10.1: #1077715# Move configuration backend API out of drafts; adjust to API changes<commit_after>/*************************************************************************
 *
 *  $RCSfile: backendfactory.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: rt $ $Date: 2003-04-17 13:13:26 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "backendfactory.hxx"

#ifndef CONFIGMGR_API_FACTORY_HXX_
#include "confapifactory.hxx"
#endif
#ifndef CONFIGMGR_BOOTSTRAPCONTEXT_HXX_
#include "bootstrapcontext.hxx"
#endif
#ifndef CONFIGMGR_BOOTSTRAP_HXX_
#include "bootstrap.hxx"
#endif
#ifndef CONFIGMGR_BACKEND_BACKENDACCESS_HXX_
#include "backendaccess.hxx"
#endif
#ifndef CONFIGMGR_SERVICEINFOHELPER_HXX_
#include "serviceinfohelper.hxx"
#endif
#ifndef CONFIGMGR_WRAPEXCEPTION_HXX
#include "wrapexception.hxx"
#endif

#ifndef _COM_SUN_STAR_CONFIGURATION_CANNOTLOADCONFIGURATIONEXCEPTION_HPP_
#include <com/sun/star/configuration/CannotLoadConfigurationException.hpp>
#endif

#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_XBACKEND_HPP_
#include <com/sun/star/configuration/backend/XBackend.hpp>
#endif
#ifndef _COM_SUN_STAR_CONFIGURATION_BACKEND_XMULTILAYERSTRATUM_HPP_
#include <com/sun/star/configuration/backend/XMultiLayerStratum.hpp>
#endif

namespace configmgr
{
// -------------------------------------------------------------------------
    namespace backend
    {
// -------------------------------------------------------------------------
        namespace uno = ::com::sun::star::uno;
        namespace lang = ::com::sun::star::lang;
        namespace backenduno = ::com::sun::star::configuration::backend;
// -------------------------------------------------------------------------
const sal_Char k_DefaultBackendWrapper[] = "com.sun.star.comp.configuration.backend.SingleBackendAdapter";
const sal_Char k_DefaultBackendService[] = "com.sun.star.comp.configuration.backend.LocalSingleBackend";

// -------------------------------------------------------------------------
const sal_Char k_DefaultBackendServiceAndImplName[]         = K_DefaultBackendServiceAndImplName ;

// -------------------------------------------------------------------------
const sal_Char k_GenericBackendServiceAndImplName[]         = "com.sun.star.configuration.backend.Backend" ;

// -------------------------------------------------------------------------
static AsciiServiceName const k_BackendServiceNames [] =
{
    k_DefaultBackendServiceAndImplName,
    k_GenericBackendServiceAndImplName,
    0
};
// -------------------------------------------------------------------------
static const ServiceRegistrationInfo k_DefaultBackendServiceInfo =
{
    k_DefaultBackendServiceAndImplName,
    k_BackendServiceNames
};
// -------------------------------------------------------------------------
static const ServiceRegistrationInfo k_GenericBackendServiceInfo =
{
    k_GenericBackendServiceAndImplName,
    k_BackendServiceNames + 1
};
// -------------------------------------------------------------------------
static const SingletonRegistrationInfo k_DefaultBackendSingletonInfo =
{
    K_DefaultBackendSingletonName,
    k_DefaultBackendServiceAndImplName,
    k_DefaultBackendServiceAndImplName,
    & k_GenericBackendServiceInfo
};
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
const SingletonRegistrationInfo * getDefaultBackendSingletonInfo()
{
    return & k_DefaultBackendSingletonInfo;
}
// -------------------------------------------------------------------------

const ServiceRegistrationInfo   * getDefaultBackendServiceInfo()
{
    return & k_DefaultBackendServiceInfo;
}
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------

uno::Reference<uno::XInterface> SAL_CALL
    getDefaultBackendSingleton( CreationContext const& xContext )
{
    OSL_ENSURE( xContext.is(), "ERROR: NULL context has no singletons" );

    UnoContextTunnel aTunnel;
    aTunnel.passthru( xContext );

    uno::Reference<uno::XInterface> xResult;

    if (xContext.is())
    try
    {
        xContext->getValueByName(SINGLETON(K_DefaultBackendSingletonName))
            >>= xResult;
    }
    catch (uno::Exception & )
    {
        // to do: really use the tunneled failure when that is set properly
        if ( aTunnel.recoverFailure(true).hasValue() )
        {
            // have a failure, but can't recover it
            // -> try to regenerate
            instantiateDefaultBackend(xContext);

            OSL_ENSURE(false, "Cannot recreate configuration backend instantiation failure - using generic error");
        }
        // cannot recover any failure
        throw;
    }

    return xResult;
}
// -------------------------------------------------------------------------

// -------------------------------------------------------------------------
// -------------------------------------------------------------------------

typedef BackendFactory::CreationContext CreationContext;
typedef uno::Sequence< uno::Any >       UnoInitArgs;
// -------------------------------------------------------------------------

static
UnoInitArgs createInitArgs(ContextReader const & _aContext)
{
    OSL_ASSERT(_aContext.hasBootstrapContext());
    uno::Sequence< uno::Any > aResult( 1 );
    aResult[0] <<= _aContext.getBootstrapContext();
    return aResult;
}
// -------------------------------------------------------------------------

static
inline
uno::Reference< uno::XInterface > createService(ContextReader const & _aCtx, UnoInitArgs const & _aInitArgs, OUString const & _aSvc)
{
    uno::Reference< lang::XMultiComponentFactory > xFactory = _aCtx.getServiceManager();
    OSL_ENSURE(xFactory.is(),"ERROR: ComponentContext has no service manager\n");
    if (!xFactory.is()) throw uno::RuntimeException( OUString::createFromAscii("ERROR: ComponentContext has no service manager\n"), NULL );
    return xFactory->createInstanceWithArgumentsAndContext( _aSvc, _aInitArgs, _aCtx.getBaseContext());
}
// -------------------------------------------------------------------------

typedef uno::Reference< backenduno::XMultiLayerStratum >    UnoSingleBackend;
typedef uno::Reference< backenduno::XBackend >              UnoBackend;

static
UnoBackend wrapSingleBackend(ContextReader const & _aSettings, UnoInitArgs const & _aInitArgs, UnoSingleBackend const & _xWrappedBackend)
{
    OSL_ASSERT(_aSettings.hasUnoBackendWrapper() || _aSettings.hasBootstrapContext());

    OUString aWrapperSvc = _aSettings.hasUnoBackendWrapper() ?
                                _aSettings.getUnoBackendWrapper() :
                                OUString::createFromAscii(k_DefaultBackendWrapper);

    OSL_ENSURE (aWrapperSvc.getLength(), "ERROR: No wrapper service for wrapped configuration");
    OSL_ENSURE (_xWrappedBackend.is(), "ERROR: No backend to wrap for wrapped configuration");

    sal_Int32 const nBaseArgsCount = _aInitArgs.getLength();
    UnoInitArgs aExtendedArgs( _aInitArgs );
    aExtendedArgs.realloc( nBaseArgsCount + 1 );
    aExtendedArgs[nBaseArgsCount] <<= _xWrappedBackend;

    return UnoBackend::query( createService(_aSettings,aExtendedArgs,aWrapperSvc) );
}
// -------------------------------------------------------------------------

static
UnoBackend createOfflineBackend(ContextReader const & _aSettings, UnoInitArgs const & _aInitArgs)
{
    OSL_ASSERT(_aSettings.hasUnoBackendWrapper() || _aSettings.hasBootstrapContext());

    UnoBackend xResult;
    if ( _aSettings.hasUnoBackendWrapper() )
    {
        OUString const aWrapperSvc = _aSettings.getUnoBackendWrapper();

        xResult = UnoBackend::query( createService(_aSettings,_aInitArgs,aWrapperSvc) );
    }

    return xResult;
}
// -------------------------------------------------------------------------

static
uno::Reference< uno::XInterface > createRealBackend(ContextReader const & _aSettings, UnoInitArgs const & _aInitArgs)
{
    OSL_ASSERT(_aSettings.hasUnoBackendService() || _aSettings.hasBootstrapContext());

    OUString const aBackendServiceName = _aSettings.hasUnoBackendService() ?
                                        _aSettings.getUnoBackendService() :
                                        OUString::createFromAscii(k_DefaultBackendService);

    uno::Reference< uno::XInterface > xResult =
        createService(_aSettings,_aInitArgs,aBackendServiceName);

    return xResult;
}
// -------------------------------------------------------------------------

static
UnoBackend createOnlineBackend(ContextReader const & _aSettings, UnoInitArgs const & _aInitArgs)
{
    OSL_ENSURE( _aSettings.isUnoBackend(), "ERROR - BackendFactory: For legacy backends use createSessionBackend()");

    UnoBackend xResult;

    uno::Reference< uno::XInterface > xRealBackend = createRealBackend(_aSettings,_aInitArgs);

    if (_aSettings.hasUnoBackendWrapper())
    {
        // try wrapping a single backend
        UnoSingleBackend xSingleRealBackend( xRealBackend, uno::UNO_QUERY);
        if (xSingleRealBackend.is())
            xResult = wrapSingleBackend(_aSettings,_aInitArgs,xSingleRealBackend);

        // if we don't have one, try using it as unwrapped backend
        else
            xResult.set(xRealBackend, uno::UNO_QUERY);
    }
    else
    {
         // look for a direct implementation of XBackend
        xResult.set(xRealBackend, uno::UNO_QUERY);
        if (!xResult.is())
        {
            // try the default wrapper if we only have a single backend
            UnoSingleBackend xSingleRealBackend( xRealBackend, uno::UNO_QUERY);
            if (xSingleRealBackend.is())
                xResult = wrapSingleBackend(_aSettings,_aInitArgs,xSingleRealBackend);

            else
                OSL_ENSURE( !xRealBackend.is(), "Configuration Backend implements no known backend interface" );
        }
    }

    return xResult;
}
// -------------------------------------------------------------------------

static UnoBackend createUnoBackend(CreationContext const& _xCtx)
{
    ContextReader aSettings(_xCtx);
    OSL_ENSURE( aSettings.isUnoBackend(), "ERROR - BackendFactory: Legacy backends are not supported any more");

    UnoInitArgs aArguments = createInitArgs(aSettings);

    sal_Bool bOffline = aSettings.hasOfflineSetting() ? aSettings.getOfflineSetting() : !aSettings.hasUnoBackendService();

    UnoBackend xResult;

    if (!bOffline)
        xResult = createOnlineBackend (aSettings,aArguments);

    if (!xResult.is())
        xResult = createOfflineBackend(aSettings,aArguments);

    return xResult;
}
// -------------------------------------------------------------------------
// to do: tunnel and raise fully typed exception information (and use it in the get..Singleton wrappers)
    #define TUNNEL_ALL_EXCEPTIONS()     \
        WRAP_CONFIGBACKEND_CREATION_EXCEPTIONS1( UnoContextTunnel::tunnelFailure, true )

// -------------------------------------------------------------------------

uno::Reference<uno::XInterface> SAL_CALL instantiateDefaultBackend( CreationContext const& xTargetContext )
{
    CreationContext xContext = UnoContextTunnel::recoverContext(xTargetContext);

    try
    {
        return createUnoBackend(xContext);
    }
    TUNNEL_ALL_EXCEPTIONS()

    OSL_ASSERT(!"unreached");
    return NULL;
}
// -------------------------------------------------------------------------

UnoBackend BackendFactory::getUnoBackend()
{
    return UnoBackend::query( getDefaultBackendSingleton(m_xCtx) );
}
// -------------------------------------------------------------------------

rtl::Reference<IMergedDataProvider> BackendFactory::createBackend()
{
    rtl::Reference< IMergedDataProvider > xBackend;

    UnoBackend xBackendService = this->getUnoBackend();

    if (xBackendService.is())
        xBackend = new BackendAccess(xBackendService, m_xCtx);

    return xBackend;
}
// -------------------------------------------------------------------------

BackendFactory BackendFactory::instance(CreationContext const & _xCtx)
{
    return BackendFactory(_xCtx);
}

//-----------------------------------------------------------------------------
    } // namespace
//-----------------------------------------------------------------------------
} // namespace
<|endoftext|>


<commit_before>/*
 * This file is part of velodyne_puck driver.
 *
 * The driver is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * The driver is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with the driver.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <velodyne_puck_decoder/velodyne_puck_decoder.h>

using namespace std;

namespace velodyne_puck_decoder {
VelodynePuckDecoder::VelodynePuckDecoder(
    ros::NodeHandle& n, ros::NodeHandle& pn):
  nh(n),
  pnh(pn),
  is_first_sweep(true),
  last_azimuth(0.0),
  sweep_start_time(0.0),
  packet_start_time(0.0),
  sweep_data(new velodyne_puck_msgs::VelodynePuckSweep()){
  return;
}

bool VelodynePuckDecoder::loadParameters() {
  pnh.param<double>("min_range", min_range, 0.5);
  pnh.param<double>("max_range", max_range, 100.0);
  pnh.param<double>("frequency", max_range, 20.0);
  return true;
}

bool VelodynePuckDecoder::createRosIO() {
  packet_sub = nh.subscribe<velodyne_puck_msgs::VelodynePuckPacket>(
      "velodyne_packet", 100, &VelodynePuckDecoder::packetCallback, this);
  sweep_pub = nh.advertise<velodyne_puck_msgs::VelodynePuckSweep>(
      "velodyne_sweep", 10);
  point_cloud_pub = nh.advertise<sensor_msgs::PointCloud2>(
      "velodyne_point_cloud", 10);
  return true;
}

bool VelodynePuckDecoder::initialize() {
  if (!loadParameters()) {
    ROS_ERROR("Cannot load all required parameters...");
    return false;
  }

  if (!createRosIO()) {
    ROS_ERROR("Cannot create ROS I/O...");
    return false;
  }

  // Fill in the altitude for each scan.
  for (size_t scan_idx = 0; scan_idx < 16; ++scan_idx) {
    size_t remapped_scan_idx = scan_idx%2 == 0 ? scan_idx/2 : scan_idx/2+8;
    sweep_data->scans[remapped_scan_idx].altitude = scan_altitude[scan_idx];
  }

  return true;
}

bool VelodynePuckDecoder::checkPacketValidity(const RawPacket* packet) {
  for (size_t blk_idx = 0; blk_idx < BLOCKS_PER_PACKET; ++blk_idx) {
    if (packet->blocks[blk_idx].header != UPPER_BANK) {
      ROS_WARN("Skip invalid VLP-16 packet: block %lu header is %x",
          blk_idx, packet->blocks[blk_idx].header);
      return false;
    }
  }
  return true;
}

void VelodynePuckDecoder::clearSweepData() {
  for (size_t i = 0; i < 16; ++i) {
    sweep_data->scans[i].points.clear();
  }
  return;
}

void VelodynePuckDecoder::decodePacket(const RawPacket* packet) {

  // Compute the azimuth angle for each firing.
  for (size_t fir_idx = 0; fir_idx < FIRINGS_PER_PACKET; fir_idx+=2) {
    size_t blk_idx = fir_idx / 2;
    firings[fir_idx].firing_azimuth = rawAzimuthToDouble(
        packet->blocks[blk_idx].rotation);
  }

  // Interpolate the azimuth values
  for (size_t fir_idx = 1; fir_idx < FIRINGS_PER_PACKET; fir_idx+=2) {
    size_t lfir_idx = fir_idx - 1;
    size_t rfir_idx = fir_idx + 1;

    if (fir_idx == FIRINGS_PER_PACKET - 1) {
      lfir_idx = fir_idx - 3;
      rfir_idx = fir_idx - 1;
    }

    double azimuth_diff = firings[rfir_idx].firing_azimuth -
      firings[lfir_idx].firing_azimuth;
    azimuth_diff = azimuth_diff < 0 ? azimuth_diff + 2*M_PI : azimuth_diff;

    firings[fir_idx].firing_azimuth =
      firings[fir_idx-1].firing_azimuth + azimuth_diff/2.0;
    firings[fir_idx].firing_azimuth  =
      firings[fir_idx].firing_azimuth > 2*M_PI ?
      firings[fir_idx].firing_azimuth-2*M_PI : firings[fir_idx].firing_azimuth;
  }

  // Fill in the distance and intensity for each firing.
  for (size_t blk_idx = 0; blk_idx < BLOCKS_PER_PACKET; ++blk_idx) {
    const RawBlock& raw_block = packet->blocks[blk_idx];

    for (size_t blk_fir_idx = 0; blk_fir_idx < FIRINGS_PER_BLOCK; ++blk_fir_idx){
      size_t fir_idx = blk_idx*FIRINGS_PER_BLOCK + blk_fir_idx;

      double azimuth_diff = 0.0;
      if (fir_idx < FIRINGS_PER_PACKET - 1)
        azimuth_diff = firings[fir_idx+1].firing_azimuth -
          firings[fir_idx].firing_azimuth;
      else
        azimuth_diff = firings[fir_idx].firing_azimuth -
          firings[fir_idx-1].firing_azimuth;

      for (size_t scan_fir_idx = 0; scan_fir_idx < SCANS_PER_FIRING; ++scan_fir_idx){
        size_t byte_idx = RAW_SCAN_SIZE * (
            SCANS_PER_FIRING*blk_fir_idx + scan_fir_idx);

        // Azimuth
        firings[fir_idx].azimuth[scan_fir_idx] = firings[fir_idx].firing_azimuth +
          (scan_fir_idx*DSR_TOFFSET/FIRING_TOFFSET) * azimuth_diff;

        // Distance
        TwoBytes raw_distance;
        raw_distance.bytes[0] = raw_block.data[byte_idx];
        raw_distance.bytes[1] = raw_block.data[byte_idx+1];
        firings[fir_idx].distance[scan_fir_idx] = static_cast<double>(
            raw_distance.distance) * DISTANCE_RESOLUTION;

        // Intensity
        firings[fir_idx].intensity[scan_fir_idx] = static_cast<double>(
            raw_block.data[byte_idx+2]);
      }
    }
  }
  return;
}

//TODO: Fill in the header of published msgs.
void VelodynePuckDecoder::packetCallback(
    const velodyne_puck_msgs::VelodynePuckPacketConstPtr& msg) {

  // Convert the msg to the raw packet type.
  const RawPacket* raw_packet = (const RawPacket*) (&(msg->data[0]));

  // Check if the packet is valid
  if (!checkPacketValidity(raw_packet)) return;

  // Decode the packet
  decodePacket(raw_packet);

  // Convert the packets
  size_t new_sweep_start = 0;
  do {
    if (firings[new_sweep_start].firing_azimuth < last_azimuth) break;
    else {
      last_azimuth = firings[new_sweep_start].firing_azimuth;
      ++new_sweep_start;
    }
  } while (new_sweep_start < FIRINGS_PER_PACKET);

  // The first sweep may not be complete. We will
  // wait for the second sweep in order to find the
  // 0 azimuth angle.
  size_t start_fir_idx = 0;
  size_t end_fir_idx = new_sweep_start;
  if (is_first_sweep &&
      new_sweep_start == FIRINGS_PER_PACKET) {
    return;
  } else {
    if (is_first_sweep) {
      ROS_INFO("Start publishing sweep data...");
      is_first_sweep = false;
      start_fir_idx = new_sweep_start;
      end_fir_idx = FIRINGS_PER_PACKET;
    }
  }

  for (size_t fir_idx = start_fir_idx; fir_idx < end_fir_idx; ++fir_idx) {
    for (size_t scan_idx = 0; scan_idx < SCANS_PER_FIRING; ++scan_idx) {
      // Check if the point is valid.
      if (!isPointInRange(firings[fir_idx].distance[scan_idx])) continue;

      // Convert the point to xyz coordinate
      double x = firings[fir_idx].distance[scan_idx] *
        cos_scan_altitude[scan_idx] * sin(firings[fir_idx].azimuth[scan_idx]);
      double y = firings[fir_idx].distance[scan_idx] *
        cos_scan_altitude[scan_idx] * cos(firings[fir_idx].azimuth[scan_idx]);
      double z = firings[fir_idx].distance[scan_idx] *
        sin_scan_altitude[scan_idx];

      double x_coord = y;
      double y_coord = -x;
      double z_coord = z;

      // Compute the time of the point
      double time = packet_start_time +
        FIRING_TOFFSET*fir_idx + DSR_TOFFSET*scan_idx;

      // Remap the index of the scan
      int remapped_scan_idx = scan_idx%2 == 0 ? scan_idx/2 : scan_idx/2+8;
      sweep_data->scans[remapped_scan_idx].points.push_back(
          velodyne_puck_msgs::VelodynePuckPoint());
      velodyne_puck_msgs::VelodynePuckPoint& new_point =
        sweep_data->scans[remapped_scan_idx].points[
        sweep_data->scans[remapped_scan_idx].points.size()-1];

      // Pack the data into point msg
      new_point.time = time;
      new_point.x = x_coord;
      new_point.y = y_coord;
      new_point.z = z_coord;
      new_point.azimuth = firings[fir_idx].azimuth[scan_idx];
      new_point.distance = firings[fir_idx].distance[scan_idx];
      new_point.intensity = firings[fir_idx].intensity[scan_idx];
    }
  }

  packet_start_time += FIRING_TOFFSET * (end_fir_idx-start_fir_idx);

  // A new sweep begins
  if (end_fir_idx != FIRINGS_PER_PACKET) {
    // Publish the last revolution
    sweep_pub.publish(sweep_data);
    clearSweepData();

    // Prepare the next revolution
    packet_start_time = 0.0;
    last_azimuth = firings[FIRINGS_PER_PACKET-1].firing_azimuth;

    start_fir_idx = end_fir_idx;
    end_fir_idx = FIRINGS_PER_PACKET;

    for (size_t fir_idx = start_fir_idx; fir_idx < end_fir_idx; ++fir_idx) {
      for (size_t scan_idx = 0; scan_idx < SCANS_PER_FIRING; ++scan_idx) {
        // Check if the point is valid.
        if (!isPointInRange(firings[fir_idx].distance[scan_idx])) continue;

        // Convert the point to xyz coordinate
        double x = firings[fir_idx].distance[scan_idx] *
          cos_scan_altitude[scan_idx] * sin(firings[fir_idx].azimuth[scan_idx]);
        double y = firings[fir_idx].distance[scan_idx] *
          cos_scan_altitude[scan_idx] * cos(firings[fir_idx].azimuth[scan_idx]);
        double z = firings[fir_idx].distance[scan_idx] *
          sin_scan_altitude[scan_idx];

        double x_coord = y;
        double y_coord = -x;
        double z_coord = z;

        // Compute the time of the point
        double time = packet_start_time +
          FIRING_TOFFSET*fir_idx + DSR_TOFFSET*scan_idx;

        // Remap the index of the scan
        int remapped_scan_idx = scan_idx%2 == 0 ? scan_idx/2 : scan_idx/2+8;
        sweep_data->scans[remapped_scan_idx].points.push_back(
            velodyne_puck_msgs::VelodynePuckPoint());
        velodyne_puck_msgs::VelodynePuckPoint& new_point =
          sweep_data->scans[remapped_scan_idx].points[
          sweep_data->scans[remapped_scan_idx].points.size()-1];

        // Pack the data into point msg
        new_point.time = time;
        new_point.x = x_coord;
        new_point.y = y_coord;
        new_point.z = z_coord;
        new_point.azimuth = firings[fir_idx].azimuth[scan_idx];
        new_point.distance = firings[fir_idx].distance[scan_idx];
        new_point.intensity = firings[fir_idx].intensity[scan_idx];
      }
    }

    packet_start_time += FIRING_TOFFSET * (end_fir_idx-start_fir_idx);
  }

  return;
}

} // end namespace velodyne_puck_decoder

<commit_msg>Fix the timing issues<commit_after>/*
 * This file is part of velodyne_puck driver.
 *
 * The driver is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * The driver is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with the driver.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <velodyne_puck_decoder/velodyne_puck_decoder.h>

using namespace std;

namespace velodyne_puck_decoder {
VelodynePuckDecoder::VelodynePuckDecoder(
    ros::NodeHandle& n, ros::NodeHandle& pn):
  nh(n),
  pnh(pn),
  is_first_sweep(true),
  last_azimuth(0.0),
  sweep_start_time(0.0),
  packet_start_time(0.0),
  sweep_data(new velodyne_puck_msgs::VelodynePuckSweep()){
  return;
}

bool VelodynePuckDecoder::loadParameters() {
  pnh.param<double>("min_range", min_range, 0.5);
  pnh.param<double>("max_range", max_range, 100.0);
  pnh.param<double>("frequency", max_range, 20.0);
  return true;
}

bool VelodynePuckDecoder::createRosIO() {
  packet_sub = nh.subscribe<velodyne_puck_msgs::VelodynePuckPacket>(
      "velodyne_packet", 100, &VelodynePuckDecoder::packetCallback, this);
  sweep_pub = nh.advertise<velodyne_puck_msgs::VelodynePuckSweep>(
      "velodyne_sweep", 10);
  point_cloud_pub = nh.advertise<sensor_msgs::PointCloud2>(
      "velodyne_point_cloud", 10);
  return true;
}

bool VelodynePuckDecoder::initialize() {
  if (!loadParameters()) {
    ROS_ERROR("Cannot load all required parameters...");
    return false;
  }

  if (!createRosIO()) {
    ROS_ERROR("Cannot create ROS I/O...");
    return false;
  }

  // Fill in the altitude for each scan.
  for (size_t scan_idx = 0; scan_idx < 16; ++scan_idx) {
    size_t remapped_scan_idx = scan_idx%2 == 0 ? scan_idx/2 : scan_idx/2+8;
    sweep_data->scans[remapped_scan_idx].altitude = scan_altitude[scan_idx];
  }

  return true;
}

bool VelodynePuckDecoder::checkPacketValidity(const RawPacket* packet) {
  for (size_t blk_idx = 0; blk_idx < BLOCKS_PER_PACKET; ++blk_idx) {
    if (packet->blocks[blk_idx].header != UPPER_BANK) {
      ROS_WARN("Skip invalid VLP-16 packet: block %lu header is %x",
          blk_idx, packet->blocks[blk_idx].header);
      return false;
    }
  }
  return true;
}

void VelodynePuckDecoder::clearSweepData() {
  for (size_t i = 0; i < 16; ++i) {
    sweep_data->scans[i].points.clear();
  }
  return;
}

void VelodynePuckDecoder::decodePacket(const RawPacket* packet) {

  // Compute the azimuth angle for each firing.
  for (size_t fir_idx = 0; fir_idx < FIRINGS_PER_PACKET; fir_idx+=2) {
    size_t blk_idx = fir_idx / 2;
    firings[fir_idx].firing_azimuth = rawAzimuthToDouble(
        packet->blocks[blk_idx].rotation);
  }

  // Interpolate the azimuth values
  for (size_t fir_idx = 1; fir_idx < FIRINGS_PER_PACKET; fir_idx+=2) {
    size_t lfir_idx = fir_idx - 1;
    size_t rfir_idx = fir_idx + 1;

    if (fir_idx == FIRINGS_PER_PACKET - 1) {
      lfir_idx = fir_idx - 3;
      rfir_idx = fir_idx - 1;
    }

    double azimuth_diff = firings[rfir_idx].firing_azimuth -
      firings[lfir_idx].firing_azimuth;
    azimuth_diff = azimuth_diff < 0 ? azimuth_diff + 2*M_PI : azimuth_diff;

    firings[fir_idx].firing_azimuth =
      firings[fir_idx-1].firing_azimuth + azimuth_diff/2.0;
    firings[fir_idx].firing_azimuth  =
      firings[fir_idx].firing_azimuth > 2*M_PI ?
      firings[fir_idx].firing_azimuth-2*M_PI : firings[fir_idx].firing_azimuth;
  }

  // Fill in the distance and intensity for each firing.
  for (size_t blk_idx = 0; blk_idx < BLOCKS_PER_PACKET; ++blk_idx) {
    const RawBlock& raw_block = packet->blocks[blk_idx];

    for (size_t blk_fir_idx = 0; blk_fir_idx < FIRINGS_PER_BLOCK; ++blk_fir_idx){
      size_t fir_idx = blk_idx*FIRINGS_PER_BLOCK + blk_fir_idx;

      double azimuth_diff = 0.0;
      if (fir_idx < FIRINGS_PER_PACKET - 1)
        azimuth_diff = firings[fir_idx+1].firing_azimuth -
          firings[fir_idx].firing_azimuth;
      else
        azimuth_diff = firings[fir_idx].firing_azimuth -
          firings[fir_idx-1].firing_azimuth;

      for (size_t scan_fir_idx = 0; scan_fir_idx < SCANS_PER_FIRING; ++scan_fir_idx){
        size_t byte_idx = RAW_SCAN_SIZE * (
            SCANS_PER_FIRING*blk_fir_idx + scan_fir_idx);

        // Azimuth
        firings[fir_idx].azimuth[scan_fir_idx] = firings[fir_idx].firing_azimuth +
          (scan_fir_idx*DSR_TOFFSET/FIRING_TOFFSET) * azimuth_diff;

        // Distance
        TwoBytes raw_distance;
        raw_distance.bytes[0] = raw_block.data[byte_idx];
        raw_distance.bytes[1] = raw_block.data[byte_idx+1];
        firings[fir_idx].distance[scan_fir_idx] = static_cast<double>(
            raw_distance.distance) * DISTANCE_RESOLUTION;

        // Intensity
        firings[fir_idx].intensity[scan_fir_idx] = static_cast<double>(
            raw_block.data[byte_idx+2]);
      }
    }
  }
  return;
}

//TODO: Fill in the header of published msgs.
void VelodynePuckDecoder::packetCallback(
    const velodyne_puck_msgs::VelodynePuckPacketConstPtr& msg) {

  // Convert the msg to the raw packet type.
  const RawPacket* raw_packet = (const RawPacket*) (&(msg->data[0]));

  // Check if the packet is valid
  if (!checkPacketValidity(raw_packet)) return;

  // Decode the packet
  decodePacket(raw_packet);

  // Convert the packets
  size_t new_sweep_start = 0;
  do {
    if (firings[new_sweep_start].firing_azimuth < last_azimuth) break;
    else {
      last_azimuth = firings[new_sweep_start].firing_azimuth;
      ++new_sweep_start;
    }
  } while (new_sweep_start < FIRINGS_PER_PACKET);

  // The first sweep may not be complete. We will
  // wait for the second sweep in order to find the
  // 0 azimuth angle.
  size_t start_fir_idx = 0;
  size_t end_fir_idx = new_sweep_start;
  if (is_first_sweep &&
      new_sweep_start == FIRINGS_PER_PACKET) {
    return;
  } else {
    if (is_first_sweep) {
      ROS_INFO("Start publishing sweep data...");
      is_first_sweep = false;
      start_fir_idx = new_sweep_start;
      end_fir_idx = FIRINGS_PER_PACKET;
    }
  }

  for (size_t fir_idx = start_fir_idx; fir_idx < end_fir_idx; ++fir_idx) {
    for (size_t scan_idx = 0; scan_idx < SCANS_PER_FIRING; ++scan_idx) {
      // Check if the point is valid.
      if (!isPointInRange(firings[fir_idx].distance[scan_idx])) continue;

      // Convert the point to xyz coordinate
      double x = firings[fir_idx].distance[scan_idx] *
        cos_scan_altitude[scan_idx] * sin(firings[fir_idx].azimuth[scan_idx]);
      double y = firings[fir_idx].distance[scan_idx] *
        cos_scan_altitude[scan_idx] * cos(firings[fir_idx].azimuth[scan_idx]);
      double z = firings[fir_idx].distance[scan_idx] *
        sin_scan_altitude[scan_idx];

      double x_coord = y;
      double y_coord = -x;
      double z_coord = z;

      // Compute the time of the point
      double time = packet_start_time +
        FIRING_TOFFSET*fir_idx + DSR_TOFFSET*scan_idx;

      // Remap the index of the scan
      int remapped_scan_idx = scan_idx%2 == 0 ? scan_idx/2 : scan_idx/2+8;
      sweep_data->scans[remapped_scan_idx].points.push_back(
          velodyne_puck_msgs::VelodynePuckPoint());
      velodyne_puck_msgs::VelodynePuckPoint& new_point =
        sweep_data->scans[remapped_scan_idx].points[
        sweep_data->scans[remapped_scan_idx].points.size()-1];

      // Pack the data into point msg
      new_point.time = time;
      new_point.x = x_coord;
      new_point.y = y_coord;
      new_point.z = z_coord;
      new_point.azimuth = firings[fir_idx].azimuth[scan_idx];
      new_point.distance = firings[fir_idx].distance[scan_idx];
      new_point.intensity = firings[fir_idx].intensity[scan_idx];
    }
  }

  packet_start_time += FIRING_TOFFSET * (end_fir_idx-start_fir_idx);

  // A new sweep begins
  if (end_fir_idx != FIRINGS_PER_PACKET) {
    // Publish the last revolution
    sweep_data->header.stamp = ros::Time(sweep_start_time);
    sweep_pub.publish(sweep_data);
    clearSweepData();

    // Prepare the next revolution
    sweep_start_time = msg->stamp.toSec() + FIRING_TOFFSET*end_fir_idx;
    packet_start_time = 0.0;
    last_azimuth = firings[FIRINGS_PER_PACKET-1].firing_azimuth;

    start_fir_idx = end_fir_idx;
    end_fir_idx = FIRINGS_PER_PACKET;

    for (size_t fir_idx = start_fir_idx; fir_idx < end_fir_idx; ++fir_idx) {
      for (size_t scan_idx = 0; scan_idx < SCANS_PER_FIRING; ++scan_idx) {
        // Check if the point is valid.
        if (!isPointInRange(firings[fir_idx].distance[scan_idx])) continue;

        // Convert the point to xyz coordinate
        double x = firings[fir_idx].distance[scan_idx] *
          cos_scan_altitude[scan_idx] * sin(firings[fir_idx].azimuth[scan_idx]);
        double y = firings[fir_idx].distance[scan_idx] *
          cos_scan_altitude[scan_idx] * cos(firings[fir_idx].azimuth[scan_idx]);
        double z = firings[fir_idx].distance[scan_idx] *
          sin_scan_altitude[scan_idx];

        double x_coord = y;
        double y_coord = -x;
        double z_coord = z;

        // Compute the time of the point
        double time = packet_start_time +
          FIRING_TOFFSET*(fir_idx-start_fir_idx) + DSR_TOFFSET*scan_idx;

        // Remap the index of the scan
        int remapped_scan_idx = scan_idx%2 == 0 ? scan_idx/2 : scan_idx/2+8;
        sweep_data->scans[remapped_scan_idx].points.push_back(
            velodyne_puck_msgs::VelodynePuckPoint());
        velodyne_puck_msgs::VelodynePuckPoint& new_point =
          sweep_data->scans[remapped_scan_idx].points[
          sweep_data->scans[remapped_scan_idx].points.size()-1];

        // Pack the data into point msg
        new_point.time = time;
        new_point.x = x_coord;
        new_point.y = y_coord;
        new_point.z = z_coord;
        new_point.azimuth = firings[fir_idx].azimuth[scan_idx];
        new_point.distance = firings[fir_idx].distance[scan_idx];
        new_point.intensity = firings[fir_idx].intensity[scan_idx];
      }
    }

    packet_start_time += FIRING_TOFFSET * (end_fir_idx-start_fir_idx);
  }

  return;
}

} // end namespace velodyne_puck_decoder

<|endoftext|>


<commit_before>/*
	Flexisip, a flexible SIP proxy server with media capabilities.
    Copyright (C) 2010  Belledonne Communications SARL.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "agent.hh"
#include "etchosts.hh"

static char const *compute_branch(nta_agent_t *sa,msg_t *msg,sip_t const *sip,char const * host,char const * port);

class ForwardModule : public Module, ModuleToolbox {
	public:
		ForwardModule(Agent *ag);
		virtual void onDeclare(ConfigStruct * module_config);
		virtual void onLoad(Agent *agent, const ConfigStruct *root);
		virtual void onRequest(std::shared_ptr<SipEvent> &ev);
		virtual void onResponse(std::shared_ptr<SipEvent> &ev);
		~ForwardModule();
	private:
		url_t* overrideDest(std::shared_ptr<SipEvent> &ev, url_t* dest);
		void checkRecordRoutes(std::shared_ptr<SipEvent> &ev, url_t *dest);
                bool isLooping(std::shared_ptr<SipEvent> &ev, const char * branch);
                unsigned int countVia(std::shared_ptr<SipEvent> &ev);

		su_home_t mHome;
		sip_route_t *mOutRoute;
		bool mRewriteReqUri;
		static ModuleInfo<ForwardModule> sInfo;
};

ModuleInfo<ForwardModule> ForwardModule::sInfo("Forward",
   "This module executes the basic routing task of SIP requests and pass them to the transport layer. "
	"It must always be enabled.");

ForwardModule::ForwardModule(Agent *ag) : Module(ag){
	su_home_init(&mHome);
	mOutRoute=NULL;
}

ForwardModule::~ForwardModule(){
	su_home_deinit(&mHome);
}

void ForwardModule::onDeclare(ConfigStruct * module_config){
	ConfigItemDescriptor items[]={
			{	String	,	"route"	, 	"A sip uri where to send all requests",	""	},
			{	Boolean	,	"rewrite-req-uri"	,	"Rewrite request-uri's host and port according to above route", "false"	},
			config_item_end
	};
	module_config->addChildrenValues(items);
}

void ForwardModule::onLoad(Agent *agent, const ConfigStruct *module_config){
	std::string route=module_config->get<ConfigString>("route")->read();
	mRewriteReqUri=module_config->get<ConfigBoolean>("rewrite-req-uri")->read();
	if (route.size()>0){
		mOutRoute=sip_route_make(&mHome,route.c_str());
		if (mOutRoute==NULL || mOutRoute->r_url->url_host==NULL){
			LOGF("Bad route parameter '%s' in configuration of Forward module",route.c_str());
		}
	}
}

url_t* ForwardModule::overrideDest(std::shared_ptr<SipEvent> &ev, url_t *dest){
	if (mOutRoute){
		dest=mOutRoute->r_url;
		if (mRewriteReqUri){
			ev->mSip->sip_request->rq_url->url_host=mOutRoute->r_url->url_host;
			ev->mSip->sip_request->rq_url->url_port=mOutRoute->r_url->url_port;
		}
	}
	return dest;
}

/* the goal of this method is to check whether we added ourself to the record route, and handle a possible
 transport change by adding a new record-route with transport updated.
 Typically, if we transfer an INVITE from TCP to UDP, we should find two consecutive record-route, first one with UDP, and second one with TCP
 so that further request from both sides are sent to the appropriate transport of flexisip, and also we don't ask to a UDP only equipment to route to TCP.
*/
void ForwardModule::checkRecordRoutes(std::shared_ptr<SipEvent> &ev, url_t *dest){
	sip_record_route_t *rr=ev->mSip->sip_record_route;
	char last_transport[16]={0};
	char next_transport[16]={0};

	if (rr){
		if (getAgent()->isUs(rr->r_url,false)){
			if (!url_param(rr->r_url->url_params,"transport",last_transport,sizeof(last_transport))){
				strncpy(last_transport,"UDP",sizeof(last_transport));
			}
			if (!url_param(dest->url_params,"transport",next_transport,sizeof(next_transport))){
				strncpy(next_transport,"UDP",sizeof(next_transport));
			}
			if (strcasecmp(next_transport,last_transport)!=0){
				addRecordRoute(ev->getHome(),getAgent(),ev->mMsg,ev->mSip,next_transport);
			}
		}
	}
}

void ForwardModule::onRequest(std::shared_ptr<SipEvent> &ev){
	size_t msg_size;
	char *buf;
	url_t* dest=NULL;
	sip_t *sip=ev->mSip;
	msg_t *msg=ev->mMsg;

	// Check max forwards
	if(sip->sip_max_forwards != NULL && sip->sip_max_forwards->mf_count <= countVia(ev))
	{
		nta_msg_treply(getSofiaAgent(), msg, 483, "Too Many Hops", SIPTAG_SERVER_STR(getAgent()->getServerString()), TAG_END());
		return;
	}

	switch(sip->sip_request->rq_method){
		case sip_method_invite:
			LOGD("This is an invite");
			break;
		case sip_method_register:
			LOGD("This is a register");

		case sip_method_ack:
		default:
			break;
	}
	dest=sip->sip_request->rq_url;
	// removes top route headers if they maches us
	while (sip->sip_route!=NULL && getAgent()->isUs(sip->sip_route->r_url) ){
		sip_route_remove(msg,sip);
	}
	if (sip->sip_route!=NULL){
		/*forward to this route*/
		dest=sip->sip_route->r_url;
	}

	/* workaround bad sip uris with two @ that results in host part being "something@somewhere" */
	if (strchr(dest->url_host,'@')!=0){
		nta_msg_treply (getSofiaAgent(),msg,400,"Bad request",SIPTAG_SERVER_STR(getAgent()->getServerString()),TAG_END());
		return;
	}

	dest=overrideDest(ev,dest);

	std::string ip;
	if (EtcHostsResolver::get()->resolve(dest->url_host,&ip)){
		LOGD("Found %s in /etc/hosts",dest->url_host);
		/* duplication dest because we don't want to modify the message with our name resolution result*/
		dest=url_hdup(ev->getHome(),dest);
		dest->url_host=ip.c_str();
	}

	// Compute branch
	char const * branch = compute_branch(getSofiaAgent(), msg, sip, dest->url_host, dest->url_port);

	// Check looping
	if (!isLooping(ev, branch)) {
		checkRecordRoutes(ev, dest);
		buf = msg_as_string(ev->getHome(), msg, NULL, 0, &msg_size);
		LOGD("About to forward request to %s:\n%s", url_as_string(ev->getHome(), dest), buf);
		nta_msg_tsend(getSofiaAgent(), msg, (url_string_t*) dest, NTATAG_BRANCH_KEY(branch), TAG_END());
	} else {
		nta_msg_treply(getSofiaAgent(), msg, 482, "Loop Detected", SIPTAG_SERVER_STR(getAgent()->getServerString()), TAG_END());
	}
}

unsigned int ForwardModule::countVia(std::shared_ptr<SipEvent> &ev) {
        uint32_t via_count = 0;
        for (sip_via_t *via = ev->mSip->sip_via; via != NULL; via = via->v_next)
                ++via_count;
        return via_count;
}

bool ForwardModule::isLooping(std::shared_ptr<SipEvent> &ev, const char * branch){
        for (sip_via_t *via = ev->mSip->sip_via; via != NULL; via = via->v_next)
        {
                if(via->v_branch != NULL && strcmp(via->v_branch, branch + 7) == 0)
                {
                    return true;
                }
        }

        return false;
}

void ForwardModule::onResponse(std::shared_ptr<SipEvent> &ev){
	char *buf;
	size_t msg_size;

	buf = msg_as_string(ev->getHome(), ev->mMsg, NULL, 0, &msg_size);
	LOGD("About to forward response:\n%s", buf);

	nta_msg_tsend(getSofiaAgent(), ev->mMsg, (url_string_t*) NULL, TAG_END());
}

#include <sofia-sip/su_md5.h>
static char const *compute_branch(nta_agent_t *sa,
	msg_t *msg,
	sip_t const *sip,
	char const * host,
	char const * port) {
	su_md5_t md5[1];
	uint8_t digest[SU_MD5_DIGEST_SIZE];
	char branch[(SU_MD5_DIGEST_SIZE * 8 + 4) / 5 + 1];
	sip_route_t const *r;

	su_md5_init(md5);

	su_md5_str0update(md5, host);
	su_md5_str0update(md5, port);

	url_update(md5, sip->sip_request->rq_url);
	if (sip->sip_call_id) {
		su_md5_str0update(md5, sip->sip_call_id->i_id);
	}
	if (sip->sip_from) {
		url_update(md5, sip->sip_from->a_url);
		su_md5_stri0update(md5, sip->sip_from->a_tag);
	}
	if (sip->sip_to) {
		url_update(md5, sip->sip_to->a_url);
		/* XXX - some broken implementations include To tag in CANCEL */
		/* su_md5_str0update(md5, sip->sip_to->a_tag); */
	}
	if (sip->sip_cseq) {
		uint32_t cseq = htonl(sip->sip_cseq->cs_seq);
		su_md5_update(md5, &cseq, sizeof (cseq));
	}

	for (r = sip->sip_route; r; r = r->r_next)
		url_update(md5, r->r_url);

	su_md5_digest(md5, digest);

	msg_random_token(branch, sizeof (branch) - 1, digest, sizeof (digest));

	return su_sprintf(msg_home(msg), "branch=z9hG4bK.%s", branch);
}

<commit_msg>Don't use shared_ptr<commit_after>/*
	Flexisip, a flexible SIP proxy server with media capabilities.
    Copyright (C) 2010  Belledonne Communications SARL.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "agent.hh"
#include "etchosts.hh"

static char const *compute_branch(nta_agent_t *sa,msg_t *msg,sip_t const *sip,char const * host,char const * port);

class ForwardModule : public Module, ModuleToolbox {
	public:
		ForwardModule(Agent *ag);
		virtual void onDeclare(ConfigStruct * module_config);
		virtual void onLoad(Agent *agent, const ConfigStruct *root);
		virtual void onRequest(SipEvent *ev);
		virtual void onResponse(SipEvent *ev);
		~ForwardModule();
	private:
		url_t* overrideDest(SipEvent *ev, url_t* dest);
		void checkRecordRoutes(SipEvent *ev, url_t *dest);
                bool isLooping(SipEvent *ev, const char * branch);
                unsigned int countVia(SipEvent *ev);

		su_home_t mHome;
		sip_route_t *mOutRoute;
		bool mRewriteReqUri;
		static ModuleInfo<ForwardModule> sInfo;
};

ModuleInfo<ForwardModule> ForwardModule::sInfo("Forward",
   "This module executes the basic routing task of SIP requests and pass them to the transport layer. "
	"It must always be enabled.");

ForwardModule::ForwardModule(Agent *ag) : Module(ag){
	su_home_init(&mHome);
	mOutRoute=NULL;
}

ForwardModule::~ForwardModule(){
	su_home_deinit(&mHome);
}

void ForwardModule::onDeclare(ConfigStruct * module_config){
	ConfigItemDescriptor items[]={
			{	String	,	"route"	, 	"A sip uri where to send all requests",	""	},
			{	Boolean	,	"rewrite-req-uri"	,	"Rewrite request-uri's host and port according to above route", "false"	},
			config_item_end
	};
	module_config->addChildrenValues(items);
}

void ForwardModule::onLoad(Agent *agent, const ConfigStruct *module_config){
	std::string route=module_config->get<ConfigString>("route")->read();
	mRewriteReqUri=module_config->get<ConfigBoolean>("rewrite-req-uri")->read();
	if (route.size()>0){
		mOutRoute=sip_route_make(&mHome,route.c_str());
		if (mOutRoute==NULL || mOutRoute->r_url->url_host==NULL){
			LOGF("Bad route parameter '%s' in configuration of Forward module",route.c_str());
		}
	}
}

url_t* ForwardModule::overrideDest(SipEvent *ev, url_t *dest){
	if (mOutRoute){
		dest=mOutRoute->r_url;
		if (mRewriteReqUri){
			ev->mSip->sip_request->rq_url->url_host=mOutRoute->r_url->url_host;
			ev->mSip->sip_request->rq_url->url_port=mOutRoute->r_url->url_port;
		}
	}
	return dest;
}

/* the goal of this method is to check whether we added ourself to the record route, and handle a possible
 transport change by adding a new record-route with transport updated.
 Typically, if we transfer an INVITE from TCP to UDP, we should find two consecutive record-route, first one with UDP, and second one with TCP
 so that further request from both sides are sent to the appropriate transport of flexisip, and also we don't ask to a UDP only equipment to route to TCP.
*/
void ForwardModule::checkRecordRoutes(SipEvent *ev, url_t *dest){
	sip_record_route_t *rr=ev->mSip->sip_record_route;
	char last_transport[16]={0};
	char next_transport[16]={0};

	if (rr){
		if (getAgent()->isUs(rr->r_url,false)){
			if (!url_param(rr->r_url->url_params,"transport",last_transport,sizeof(last_transport))){
				strncpy(last_transport,"UDP",sizeof(last_transport));
			}
			if (!url_param(dest->url_params,"transport",next_transport,sizeof(next_transport))){
				strncpy(next_transport,"UDP",sizeof(next_transport));
			}
			if (strcasecmp(next_transport,last_transport)!=0){
				addRecordRoute(ev->getHome(),getAgent(),ev->mMsg,ev->mSip,next_transport);
			}
		}
	}
}

void ForwardModule::onRequest(SipEvent *ev){
	size_t msg_size;
	char *buf;
	url_t* dest=NULL;
	sip_t *sip=ev->mSip;
	msg_t *msg=ev->mMsg;

	// Check max forwards
	if(sip->sip_max_forwards != NULL && sip->sip_max_forwards->mf_count <= countVia(ev))
	{
		nta_msg_treply(getSofiaAgent(), msg, 483, "Too Many Hops", SIPTAG_SERVER_STR(getAgent()->getServerString()), TAG_END());
		return;
	}

	switch(sip->sip_request->rq_method){
		case sip_method_invite:
			LOGD("This is an invite");
			break;
		case sip_method_register:
			LOGD("This is a register");

		case sip_method_ack:
		default:
			break;
	}
	dest=sip->sip_request->rq_url;
	// removes top route headers if they maches us
	while (sip->sip_route!=NULL && getAgent()->isUs(sip->sip_route->r_url) ){
		sip_route_remove(msg,sip);
	}
	if (sip->sip_route!=NULL){
		/*forward to this route*/
		dest=sip->sip_route->r_url;
	}

	/* workaround bad sip uris with two @ that results in host part being "something@somewhere" */
	if (strchr(dest->url_host,'@')!=0){
		nta_msg_treply (getSofiaAgent(),msg,400,"Bad request",SIPTAG_SERVER_STR(getAgent()->getServerString()),TAG_END());
		return;
	}

	dest=overrideDest(ev,dest);

	std::string ip;
	if (EtcHostsResolver::get()->resolve(dest->url_host,&ip)){
		LOGD("Found %s in /etc/hosts",dest->url_host);
		/* duplication dest because we don't want to modify the message with our name resolution result*/
		dest=url_hdup(ev->getHome(),dest);
		dest->url_host=ip.c_str();
	}

	// Compute branch
	char const * branch = compute_branch(getSofiaAgent(), msg, sip, dest->url_host, dest->url_port);

	// Check looping
	if (!isLooping(ev, branch)) {
		checkRecordRoutes(ev, dest);
		buf = msg_as_string(ev->getHome(), msg, NULL, 0, &msg_size);
		LOGD("About to forward request to %s:\n%s", url_as_string(ev->getHome(), dest), buf);
		nta_msg_tsend(getSofiaAgent(), msg, (url_string_t*) dest, NTATAG_BRANCH_KEY(branch), TAG_END());
	} else {
		nta_msg_treply(getSofiaAgent(), msg, 482, "Loop Detected", SIPTAG_SERVER_STR(getAgent()->getServerString()), TAG_END());
	}
}

unsigned int ForwardModule::countVia(SipEvent *ev) {
        uint32_t via_count = 0;
        for (sip_via_t *via = ev->mSip->sip_via; via != NULL; via = via->v_next)
                ++via_count;
        return via_count;
}

bool ForwardModule::isLooping(SipEvent *ev, const char * branch){
        for (sip_via_t *via = ev->mSip->sip_via; via != NULL; via = via->v_next)
        {
                if(via->v_branch != NULL && strcmp(via->v_branch, branch + 7) == 0)
                {
                    return true;
                }
        }

        return false;
}

void ForwardModule::onResponse(SipEvent *ev){
	char *buf;
	size_t msg_size;

	buf = msg_as_string(ev->getHome(), ev->mMsg, NULL, 0, &msg_size);
	LOGD("About to forward response:\n%s", buf);

	nta_msg_tsend(getSofiaAgent(), ev->mMsg, (url_string_t*) NULL, TAG_END());
}

#include <sofia-sip/su_md5.h>
static char const *compute_branch(nta_agent_t *sa,
	msg_t *msg,
	sip_t const *sip,
	char const * host,
	char const * port) {
	su_md5_t md5[1];
	uint8_t digest[SU_MD5_DIGEST_SIZE];
	char branch[(SU_MD5_DIGEST_SIZE * 8 + 4) / 5 + 1];
	sip_route_t const *r;

	su_md5_init(md5);

	su_md5_str0update(md5, host);
	su_md5_str0update(md5, port);

	url_update(md5, sip->sip_request->rq_url);
	if (sip->sip_call_id) {
		su_md5_str0update(md5, sip->sip_call_id->i_id);
	}
	if (sip->sip_from) {
		url_update(md5, sip->sip_from->a_url);
		su_md5_stri0update(md5, sip->sip_from->a_tag);
	}
	if (sip->sip_to) {
		url_update(md5, sip->sip_to->a_url);
		/* XXX - some broken implementations include To tag in CANCEL */
		/* su_md5_str0update(md5, sip->sip_to->a_tag); */
	}
	if (sip->sip_cseq) {
		uint32_t cseq = htonl(sip->sip_cseq->cs_seq);
		su_md5_update(md5, &cseq, sizeof (cseq));
	}

	for (r = sip->sip_route; r; r = r->r_next)
		url_update(md5, r->r_url);

	su_md5_digest(md5, digest);

	msg_random_token(branch, sizeof (branch) - 1, digest, sizeof (digest));

	return su_sprintf(msg_home(msg), "branch=z9hG4bK.%s", branch);
}

<|endoftext|>


<commit_before>#include <memory>

std::shared_ptr<rusql::Database> get_database(int argc, char *argv[]) {
	if(argc == 1) {
		std::cerr << "1..0 # Skipped: Embedded mode not supported yet" << std::endl;
		exit(0);
		//return new rusql::Database(rusql::Database::Embedded);
	} else if(argc == 5) {
		return std::make_shared<rusql::Database>(
				rusql::Database::ConstructionInfo{argv[1], argv[2], argv[3], argv[4]});
	} else {
		std::cout << "1..0 # Skipped: Invalid parameters" << std::endl;
		exit(0);
	}
}
<commit_msg>On invalid parameters to a test, give correct skip output and give it on stdout instead of stderr.<commit_after>#include <memory>

std::shared_ptr<rusql::Database> get_database(int argc, char *argv[]) {
	if(argc == 1) {
		std::cout << "1..0 # SKIP Embedded mode not supported yet" << std::endl;
		exit(0);
		//return new rusql::Database(rusql::Database::Embedded);
	} else if(argc == 5) {
		return std::make_shared<rusql::Database>(
				rusql::Database::ConstructionInfo{argv[1], argv[2], argv[3], argv[4]});
	} else {
		std::cout << "1..0 # SKIP Invalid parameters" << std::endl;
		exit(0);
	}
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: backendfactory.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: jb $ $Date: 2002-09-02 17:23:43 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "backendfactory.hxx"

#ifndef CONFIGMGR_BOOTSTRAPCONTEXT_HXX_
#include "bootstrapcontext.hxx"
#endif
#ifndef CONFIGMGR_BOOTSTRAP_HXX_
#include "bootstrap.hxx"
#endif
#ifndef CONFIGMGR_BACKEND_BACKENDACCESS_HXX_
#include "backendaccess.hxx"
#endif
#ifndef CONFIGMGR_BACKENDWRAP_HXX
#include "backendwrap.hxx"
#endif

#ifndef _COM_SUN_STAR_CONFIGURATION_CANNOTLOADCONFIGURATIONEXCEPTION_HPP_
#include <com/sun/star/configuration/CannotLoadConfigurationException.hpp>
#endif

#include <drafts/com/sun/star/configuration/backend/XBackend.hpp>
#include <drafts/com/sun/star/configuration/backend/XSingleBackend.hpp>

namespace configmgr
{
// -------------------------------------------------------------------------
    namespace backend
    {
// -------------------------------------------------------------------------
        namespace uno = ::com::sun::star::uno;
        namespace lang = ::com::sun::star::lang;
        namespace backenduno = drafts::com::sun::star::configuration::backend;
// -------------------------------------------------------------------------
const sal_Char k_DefaultBackendWrapper[] = "com.sun.star.comp.configuration.backend.SingleBackendAdapter";
const sal_Char k_DefaultBackendService[] = "com.sun.star.comp.configuration.backend.LocalSingleBackend";
// -------------------------------------------------------------------------
typedef uno::Sequence< uno::Any > UnoInitArgs;

static
UnoInitArgs createInitArgs(ConnectionSettings const & _aSettings)
{
    uno::Reference< uno::XCurrentContext > xBootstrapArgs = new BootstrapContext(_aSettings.getUnoSettings());
    uno::Sequence< uno::Any > aResult( 1 );
    aResult[0] <<= xBootstrapArgs;
    return aResult;
}
// -------------------------------------------------------------------------

typedef BackendFactory::CreationContext CreationContext;

static
inline
uno::Reference< uno::XInterface > createService(CreationContext const & _xCtx, UnoInitArgs const & _aInitArgs, OUString const & _aSvc)
{
    OSL_ASSERT(_xCtx.is());
    return _xCtx->createInstanceWithArguments( _aSvc, _aInitArgs);
}
// -------------------------------------------------------------------------

typedef uno::Reference< backenduno::XSingleBackend >    UnoSingleBackend;
typedef uno::Reference< backenduno::XBackend >          UnoBackend;

static
UnoBackend wrapSingleBackend(ConnectionSettings const & _aSettings, CreationContext const & _xCtx, UnoInitArgs const & _aInitArgs, UnoSingleBackend const & _xWrappedBackend)
{
    OUString aWrapperSvc = _aSettings.hasUnoBackendWrapper() ?
                                _aSettings.getUnoBackendWrapper() :
                                OUString::createFromAscii(k_DefaultBackendWrapper);

    OSL_ENSURE (aWrapperSvc.getLength(), "ERROR: No wrapper service for wrapped configuration");
    OSL_ENSURE (_xWrappedBackend.is(), "ERROR: No backend to wrap for wrapped configuration");

    sal_Int32 const nBaseArgsCount = _aInitArgs.getLength();
    UnoInitArgs aExtendedArgs( _aInitArgs );
    aExtendedArgs.realloc( nBaseArgsCount + 1 );
    aExtendedArgs[nBaseArgsCount] <<= _xWrappedBackend;

    return UnoBackend::query( createService(_xCtx,aExtendedArgs,aWrapperSvc) );
}
// -------------------------------------------------------------------------

static
UnoBackend createOfflineBackend(ConnectionSettings const & _aSettings, CreationContext const & _xCtx, UnoInitArgs const & _aInitArgs)
{
    UnoBackend xResult;
    if ( _aSettings.hasUnoBackendWrapper() )
    {
        OUString const aWrapperSvc = _aSettings.getUnoBackendWrapper();

        xResult = UnoBackend::query( createService(_xCtx,_aInitArgs,aWrapperSvc) );
    }

    return xResult;
}
// -------------------------------------------------------------------------

static
sal_Bool createOfflineBackend_nothrow(UnoBackend & _rxResult, ConnectionSettings const & _aSettings, CreationContext const & _xCtx, UnoInitArgs const & _aInitArgs)
{
    try
    {
        _rxResult = createOfflineBackend(_aSettings,_xCtx,_aInitArgs);
        return _rxResult.is();
    }
    catch (uno::Exception &)
    {
        return false;
    }
}
// -------------------------------------------------------------------------

static
uno::Reference< uno::XInterface > createRealBackend(ConnectionSettings const & _aSettings, CreationContext const & _xCtx, UnoInitArgs const & _aInitArgs)
{
    OUString const aBackendServiceName = _aSettings.hasUnoBackendService() ?
                                        _aSettings.getUnoBackendService() :
                                        OUString::createFromAscii(k_DefaultBackendService);

    uno::Reference< uno::XInterface > xResult =
        createService(_xCtx,_aInitArgs,_aSettings.getUnoBackendService());

    return xResult;
}
// -------------------------------------------------------------------------

static
UnoBackend createOnlineBackend(ConnectionSettings const & _aSettings, CreationContext const & _xCtx, UnoInitArgs const & _aInitArgs)
{
    OSL_ENSURE( _aSettings.isUnoBackend(), "ERROR - BackendFactory: For legacy backends use createSessionBackend()");

    UnoBackend xResult;

    uno::Reference< uno::XInterface > xRealBackend = createRealBackend(_aSettings,_xCtx,_aInitArgs);

    if (_aSettings.hasUnoBackendWrapper())
    {
        // try wrapping a single backend
        UnoSingleBackend xSingleRealBackend( xRealBackend, uno::UNO_QUERY);
        if (xSingleRealBackend.is())
            xResult = wrapSingleBackend(_aSettings,_xCtx,_aInitArgs,xSingleRealBackend);

        // if we don't have one, try using it as unwrapped backend
        else
            xResult.set(xRealBackend, uno::UNO_QUERY);
    }
    else
    {
         // look for a direct implementation of XBackend
        xResult.set(xRealBackend, uno::UNO_QUERY);
        if (!xResult.is())
        {
            // try the default wrapper if we only have a single backend
            UnoSingleBackend xSingleRealBackend( xRealBackend, uno::UNO_QUERY);
            if (xSingleRealBackend.is())
                xResult = wrapSingleBackend(_aSettings,_xCtx,_aInitArgs,xSingleRealBackend);

            else
                OSL_ENSURE( !xRealBackend.is(), "Configuration Backend implements no known backendinterface" );
        }
    }

    return xResult;
}
// -------------------------------------------------------------------------

static
UnoBackend createUnoBackend(ConnectionSettings const & _aSettings, CreationContext const & _xCtx)
{
    UnoInitArgs aArguments = createInitArgs(_aSettings);

    UnoBackend xResult;
    try
    {
       xResult = createOnlineBackend(_aSettings,_xCtx,aArguments);
    }

    // for CannotLoadConfigurationException, try fallback to wrapper-only (offline) mode
    catch (com::sun::star::configuration::CannotLoadConfigurationException & )
    {
        if (!createOfflineBackend_nothrow(xResult,_aSettings,_xCtx,aArguments))
            throw;
    }

    if (!xResult.is())
        xResult = createOfflineBackend(_aSettings,_xCtx,aArguments);

    return xResult;
}
// -------------------------------------------------------------------------

rtl::Reference<IMergedDataProvider>
    BackendFactory::createBackend(ConnectionSettings const & _aSettings, CreationContext const & _xCtx)
{
    OSL_ENSURE( _aSettings.isUnoBackend(), "ERROR - BackendFactory: For legacy backends use createSessionBackend()");

    rtl::Reference< IMergedDataProvider > xBackend;

    UnoBackend xBackendService = createUnoBackend(_aSettings, _xCtx);

    if (xBackendService.is())
        xBackend = new BackendAccess(xBackendService, _xCtx);

    return xBackend;
}
// -------------------------------------------------------------------------

rtl::Reference<IMergedDataProvider>
    BackendFactory::createSessionBackend(IConfigSession * _pSession,
                                            TypeConverterRef const & _xTCV)
{
    rtl::Reference< IMergedDataProvider > xBackend;

    if (_pSession)
        xBackend = wrapSession(*_pSession,_xTCV);

    return xBackend;
}
// -------------------------------------------------------------------------

BackendFactory & BackendFactory::instance()
{
    static BackendFactory aStaticFactory;
    return aStaticFactory;
}

//-----------------------------------------------------------------------------
    } // namespace
//-----------------------------------------------------------------------------
} // namespace
<commit_msg>#102850# Fallback to offline mode now done externally<commit_after>/*************************************************************************
 *
 *  $RCSfile: backendfactory.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: jb $ $Date: 2002-09-19 10:53:21 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "backendfactory.hxx"

#ifndef CONFIGMGR_BOOTSTRAPCONTEXT_HXX_
#include "bootstrapcontext.hxx"
#endif
#ifndef CONFIGMGR_BOOTSTRAP_HXX_
#include "bootstrap.hxx"
#endif
#ifndef CONFIGMGR_BACKEND_BACKENDACCESS_HXX_
#include "backendaccess.hxx"
#endif
#ifndef CONFIGMGR_BACKENDWRAP_HXX
#include "backendwrap.hxx"
#endif

#ifndef _COM_SUN_STAR_CONFIGURATION_CANNOTLOADCONFIGURATIONEXCEPTION_HPP_
#include <com/sun/star/configuration/CannotLoadConfigurationException.hpp>
#endif

#include <drafts/com/sun/star/configuration/backend/XBackend.hpp>
#include <drafts/com/sun/star/configuration/backend/XSingleBackend.hpp>

namespace configmgr
{
// -------------------------------------------------------------------------
    namespace backend
    {
// -------------------------------------------------------------------------
        namespace uno = ::com::sun::star::uno;
        namespace lang = ::com::sun::star::lang;
        namespace backenduno = drafts::com::sun::star::configuration::backend;
// -------------------------------------------------------------------------
const sal_Char k_DefaultBackendWrapper[] = "com.sun.star.comp.configuration.backend.SingleBackendAdapter";
const sal_Char k_DefaultBackendService[] = "com.sun.star.comp.configuration.backend.LocalSingleBackend";
// -------------------------------------------------------------------------
typedef uno::Sequence< uno::Any > UnoInitArgs;

static
UnoInitArgs createInitArgs(ConnectionSettings const & _aSettings)
{
    uno::Reference< uno::XCurrentContext > xBootstrapArgs = new BootstrapContext(_aSettings.getUnoSettings());
    uno::Sequence< uno::Any > aResult( 1 );
    aResult[0] <<= xBootstrapArgs;
    return aResult;
}
// -------------------------------------------------------------------------

typedef BackendFactory::CreationContext CreationContext;

static
inline
uno::Reference< uno::XInterface > createService(CreationContext const & _xCtx, UnoInitArgs const & _aInitArgs, OUString const & _aSvc)
{
    OSL_ASSERT(_xCtx.is());
    return _xCtx->createInstanceWithArguments( _aSvc, _aInitArgs);
}
// -------------------------------------------------------------------------

typedef uno::Reference< backenduno::XSingleBackend >    UnoSingleBackend;
typedef uno::Reference< backenduno::XBackend >          UnoBackend;

static
UnoBackend wrapSingleBackend(ConnectionSettings const & _aSettings, CreationContext const & _xCtx, UnoInitArgs const & _aInitArgs, UnoSingleBackend const & _xWrappedBackend)
{
    OUString aWrapperSvc = _aSettings.hasUnoBackendWrapper() ?
                                _aSettings.getUnoBackendWrapper() :
                                OUString::createFromAscii(k_DefaultBackendWrapper);

    OSL_ENSURE (aWrapperSvc.getLength(), "ERROR: No wrapper service for wrapped configuration");
    OSL_ENSURE (_xWrappedBackend.is(), "ERROR: No backend to wrap for wrapped configuration");

    sal_Int32 const nBaseArgsCount = _aInitArgs.getLength();
    UnoInitArgs aExtendedArgs( _aInitArgs );
    aExtendedArgs.realloc( nBaseArgsCount + 1 );
    aExtendedArgs[nBaseArgsCount] <<= _xWrappedBackend;

    return UnoBackend::query( createService(_xCtx,aExtendedArgs,aWrapperSvc) );
}
// -------------------------------------------------------------------------

static
UnoBackend createOfflineBackend(ConnectionSettings const & _aSettings, CreationContext const & _xCtx, UnoInitArgs const & _aInitArgs)
{
    UnoBackend xResult;
    if ( _aSettings.hasUnoBackendWrapper() )
    {
        OUString const aWrapperSvc = _aSettings.getUnoBackendWrapper();

        xResult = UnoBackend::query( createService(_xCtx,_aInitArgs,aWrapperSvc) );
    }

    return xResult;
}
// -------------------------------------------------------------------------

static
uno::Reference< uno::XInterface > createRealBackend(ConnectionSettings const & _aSettings, CreationContext const & _xCtx, UnoInitArgs const & _aInitArgs)
{
    OUString const aBackendServiceName = _aSettings.hasUnoBackendService() ?
                                        _aSettings.getUnoBackendService() :
                                        OUString::createFromAscii(k_DefaultBackendService);

    uno::Reference< uno::XInterface > xResult =
        createService(_xCtx,_aInitArgs,aBackendServiceName);

    return xResult;
}
// -------------------------------------------------------------------------

static
UnoBackend createOnlineBackend(ConnectionSettings const & _aSettings, CreationContext const & _xCtx, UnoInitArgs const & _aInitArgs)
{
    OSL_ENSURE( _aSettings.isUnoBackend(), "ERROR - BackendFactory: For legacy backends use createSessionBackend()");

    UnoBackend xResult;

    uno::Reference< uno::XInterface > xRealBackend = createRealBackend(_aSettings,_xCtx,_aInitArgs);

    if (_aSettings.hasUnoBackendWrapper())
    {
        // try wrapping a single backend
        UnoSingleBackend xSingleRealBackend( xRealBackend, uno::UNO_QUERY);
        if (xSingleRealBackend.is())
            xResult = wrapSingleBackend(_aSettings,_xCtx,_aInitArgs,xSingleRealBackend);

        // if we don't have one, try using it as unwrapped backend
        else
            xResult.set(xRealBackend, uno::UNO_QUERY);
    }
    else
    {
         // look for a direct implementation of XBackend
        xResult.set(xRealBackend, uno::UNO_QUERY);
        if (!xResult.is())
        {
            // try the default wrapper if we only have a single backend
            UnoSingleBackend xSingleRealBackend( xRealBackend, uno::UNO_QUERY);
            if (xSingleRealBackend.is())
                xResult = wrapSingleBackend(_aSettings,_xCtx,_aInitArgs,xSingleRealBackend);

            else
                OSL_ENSURE( !xRealBackend.is(), "Configuration Backend implements no known backend interface" );
        }
    }

    return xResult;
}
// -------------------------------------------------------------------------

static
UnoBackend createUnoBackend(ConnectionSettings const & _aSettings, CreationContext const & _xCtx)
{
    UnoInitArgs aArguments = createInitArgs(_aSettings);

    sal_Bool bOffline = _aSettings.hasOfflineSetting() ? _aSettings.getOfflineSetting() : !_aSettings.hasUnoBackendService();

    UnoBackend xResult;

    if (!bOffline)
        xResult = createOnlineBackend(_aSettings,_xCtx,aArguments);

    if (!xResult.is())
        xResult = createOfflineBackend(_aSettings,_xCtx,aArguments);

    return xResult;
}
// -------------------------------------------------------------------------

rtl::Reference<IMergedDataProvider>
    BackendFactory::createBackend(ConnectionSettings const & _aSettings, CreationContext const & _xCtx)
{
    OSL_ENSURE( _aSettings.isUnoBackend(), "ERROR - BackendFactory: For legacy backends use createSessionBackend()");

    rtl::Reference< IMergedDataProvider > xBackend;

    UnoBackend xBackendService = createUnoBackend(_aSettings, _xCtx);

    if (xBackendService.is())
        xBackend = new BackendAccess(xBackendService, _xCtx);

    return xBackend;
}
// -------------------------------------------------------------------------

rtl::Reference<IMergedDataProvider>
    BackendFactory::createSessionBackend(IConfigSession * _pSession,
                                            TypeConverterRef const & _xTCV)
{
    rtl::Reference< IMergedDataProvider > xBackend;

    if (_pSession)
        xBackend = wrapSession(*_pSession,_xTCV);

    return xBackend;
}
// -------------------------------------------------------------------------

BackendFactory & BackendFactory::instance()
{
    static BackendFactory aStaticFactory;
    return aStaticFactory;
}

//-----------------------------------------------------------------------------
    } // namespace
//-----------------------------------------------------------------------------
} // namespace
<|endoftext|>