<commit_before>/*************************************************************************
 *
 *  $RCSfile: menudispatcher.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: vg $ $Date: 2003-06-10 09:09:50 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#ifndef __FRAMEWORK_DISPATCH_MENUDISPATCHER_HXX_
#define __FRAMEWORK_DISPATCH_MENUDISPATCHER_HXX_

//_________________________________________________________________________________________________________________
//  my own includes
//_________________________________________________________________________________________________________________

#ifndef __FRAMEWORK_CLASSES_TASKCREATOR_HXX_
#include <classes/taskcreator.hxx>
#endif

#ifndef __FRAMEWORK_SERVICES_FRAME_HXX_
#include <services/frame.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_GENERIC_HXX_
#include <macros/generic.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_XINTERFACE_HXX_
#include <macros/xinterface.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_XTYPEPROVIDER_HXX_
#include <macros/xtypeprovider.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_DEBUG_HXX_
#include <macros/debug.hxx>
#endif

#ifndef __FRAMEWORK_THREADHELP_THREADHELPBASE_HXX_
#include <threadhelp/threadhelpbase.hxx>
#endif

#ifndef __FRAMEWORK_CLASSES_MENUMANAGER_HXX_
#include <classes/menumanager.hxx>
#endif

#ifndef __FRAMEWORK_GENERAL_H_
#include <general.h>
#endif

#ifndef __FRAMEWORK_STDTYPES_H_
#include <stdtypes.h>
#endif

//_________________________________________________________________________________________________________________
//  interface includes
//_________________________________________________________________________________________________________________

#ifndef _COM_SUN_STAR_LANG_XTYPEPROVIDER_HPP_
#include <com/sun/star/lang/XTypeProvider.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_XDISPATCH_HPP_
#include <com/sun/star/frame/XDispatch.hpp>
#endif

#ifndef _COM_SUN_STAR_UTIL_URL_HPP_
#include <com/sun/star/util/URL.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_DISPATCHDESCRIPTOR_HPP_
#include <com/sun/star/frame/DispatchDescriptor.hpp>
#endif

#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_
#include <com/sun/star/beans/PropertyValue.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_XSTATUSLISTENER_HPP_
#include <com/sun/star/frame/XStatusListener.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_XFRAMELOADER_HPP_
#include <com/sun/star/frame/XFrameLoader.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_XLOADEVENTLISTENER_HPP_
#include <com/sun/star/frame/XLoadEventListener.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_XDESKTOP_HPP_
#include <com/sun/star/frame/XDesktop.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_FEATURESTATEEVENT_HPP_
#include <com/sun/star/frame/FeatureStateEvent.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_XFRAMEACTIONLISTENER_HPP_
#include <com/sun/star/frame/XFrameActionListener.hpp>
#endif

//_________________________________________________________________________________________________________________
//  other includes
//_________________________________________________________________________________________________________________

#ifndef _CPPUHELPER_WEAK_HXX_
#include <cppuhelper/weak.hxx>
#endif

#ifndef _CPPUHELPER_WEAKREF_HXX_
#include <cppuhelper/weakref.hxx>
#endif

#ifndef _CPPUHELPER_INTERFACECONTAINER_H_
#include <cppuhelper/interfacecontainer.h>
#endif

//_________________________________________________________________________________________________________________
//  namespace
//_________________________________________________________________________________________________________________

namespace framework{

//_________________________________________________________________________________________________________________
//  exported const
//_________________________________________________________________________________________________________________

//_________________________________________________________________________________________________________________
//  exported definitions
//_________________________________________________________________________________________________________________

/*-************************************************************************************************************//**
    We must save informations about our listener and URL for listening.
    We implement this as a hashtable for strings.
*//*-*************************************************************************************************************/

typedef ::cppu::OMultiTypeInterfaceContainerHelperVar<  ::rtl::OUString         ,
                                                        OUStringHashCode        ,
                                                        std::equal_to< ::rtl::OUString > > IMPL_ListenerHashContainer;

/*-************************************************************************************************************//**
    @short          helper for desktop only(!) to create new tasks on demand for dispatches
    @descr          Use this class as member only! Never use it as baseclass.
                    XInterface will be ambigous and we hold a weakcss::uno::Reference to ouer OWNER - not to ouer SUPERCLASS!

    @implements     XInterface
                    XDispatch
                    XLoadEventListener
                    XFrameActionListener
                    XEventListener
    @base           ThreadHelpBase
                    OWeakObject

    @devstatus      ready to use
*//*-*************************************************************************************************************/
class MenuDispatcher   :   // interfaces
                                public css::lang::XTypeProvider         ,
                                public css::frame::XDispatch            ,
                                public css::frame::XFrameActionListener ,
                                // baseclasses
                                // Order is neccessary for right initialization!
                                public ThreadHelpBase                       ,
                                public cppu::OWeakObject
{
    //-------------------------------------------------------------------------------------------------------------
    //  public methods
    //-------------------------------------------------------------------------------------------------------------

    public:

        //---------------------------------------------------------------------------------------------------------
        //  constructor / destructor
        //---------------------------------------------------------------------------------------------------------

        /*-****************************************************************************************************//**
            @short      standard ctor
            @descr      These initialize a new instance of ths class with needed informations for work.

            @seealso    using at owner

            @param      "xFactory"  , css::uno::Reference to servicemanager for creation of new services
            @param      "xOwner"    , css::uno::Reference to our owner, the Desktop!!!
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        MenuDispatcher(    const   css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory    ,
                            const   css::uno::Reference< css::frame::XFrame >&              xOwner      );

        //---------------------------------------------------------------------------------------------------------
        //  XInterface
        //---------------------------------------------------------------------------------------------------------

        DECLARE_XINTERFACE
        DECLARE_XTYPEPROVIDER

        //---------------------------------------------------------------------------------------------------------
        //  XDispatch
        //---------------------------------------------------------------------------------------------------------

        /*-****************************************************************************************************//**
            @short      dispatch URL with arguments
            @descr      Every dispatch create a new task. If load of URL failed task will deleted automaticly!

            @seealso    -

            @param      "aURL"          , URL to dispatch.
            @param      "seqArguments"  , list of optional arguments.
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        virtual void SAL_CALL dispatch( const   css::util::URL&                                     aURL            ,
                                        const   css::uno::Sequence< css::beans::PropertyValue >&    seqProperties   ) throw( css::uno::RuntimeException );

        /*-****************************************************************************************************//**
            @short      add listener for state events
            @descr      You can add a listener to get information about status of dispatch: OK or Failed.

            @seealso    method loadFinished()
            @seealso    method loadCancelled()

            @param      "xControl"  , css::uno::Reference to a valid listener for state events.
            @param      "aURL"      , URL about listener will be informed, if something occured.
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        virtual void SAL_CALL addStatusListener(    const   css::uno::Reference< css::frame::XStatusListener >& xControl,
                                                    const   css::util::URL&                                     aURL    ) throw( css::uno::RuntimeException );

        /*-****************************************************************************************************//**
            @short      remove listener for state events
            @descr      You can remove a listener if information of dispatch isn't important for you any longer.

            @seealso    method loadFinished()
            @seealso    method loadCancelled()

            @param      "xControl"  , css::uno::Reference to a valid listener.
            @param      "aURL"      , URL on which listener has registered.
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        virtual void SAL_CALL removeStatusListener( const   css::uno::Reference< css::frame::XStatusListener >& xControl,
                                                    const   css::util::URL&                                     aURL    ) throw( css::uno::RuntimeException );

        //---------------------------------------------------------------------------------------------------------
        //   XFrameActionListener
        //---------------------------------------------------------------------------------------------------------

        virtual void SAL_CALL frameAction( const css::frame::FrameActionEvent& aEvent ) throw ( css::uno::RuntimeException );

        //---------------------------------------------------------------------------------------------------------
        //   XEventListener
        //---------------------------------------------------------------------------------------------------------

        /*-****************************************************************************************************//**
            @short      dispose current instance
            @descr      If service helper isn't required any longer call this method to release all used ressources.

            @seealso    -

            @param      "aEvent", information about source of this event.
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        void SAL_CALL disposing( const EVENTOBJECT& aEvent ) throw( css::uno::RuntimeException );

    //-------------------------------------------------------------------------------------------------------------
    //  protected methods
    //-------------------------------------------------------------------------------------------------------------

    protected:

        /*-****************************************************************************************************//**
            @short      standard destructor
            @descr      This method destruct an instance of this class and clear some member.
                        This method is protected, because its not allowed to use an instance of this class as a member!
                        You MUST use a pointer.

            @seealso    -

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        virtual ~MenuDispatcher();

    //-------------------------------------------------------------------------------------------------------------
    //  private methods
    //-------------------------------------------------------------------------------------------------------------

    private:

        DECL_LINK( Close_Impl, void* );

        /*-****************************************************************************************************//**
            @short      -
            @descr      -

            @seealso    -

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        void impl_sendStatusEvent(  const   css::uno::Reference< XFRAME >&  xEventSource    ,
                                    const   ::rtl::OUString&        sURL            ,
                                            sal_Bool                bLoadState      );

        /*-****************************************************************************************************//**
            @short      -
            @descr      -

            @seealso    -

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        sal_Bool impl_setMenuBar( MenuBar* pMenuBar, sal_Bool bMenuFromResource = sal_False );

        /*-****************************************************************************************************//**
            @short      -
            @descr      -

            @seealso    -

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        void impl_setAccelerators( Menu* pMenu, const Accelerator& aAccel );

    //-------------------------------------------------------------------------------------------------------------
    //  debug methods
    //  (should be private everyway!)
    //-------------------------------------------------------------------------------------------------------------

        /*-****************************************************************************************************//**
            @short      debug-method to check incoming parameter of some other mehods of this class
            @descr      The following methods are used to check parameters for other methods
                        of this class. The return value is used directly for an ASSERT(...).

            @seealso    ASSERTs in implementation!

            @param      css::uno::References to checking variables
            @return     sal_False on invalid parameter<BR>
                        sal_True  otherway

            @onerror    -
        *//*-*****************************************************************************************************/

    #ifdef ENABLE_ASSERTIONS

    private:

        static sal_Bool impldbg_checkParameter_MenuDispatcher      (   const   css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory        ,
                                                                        const   css::uno::Reference< css::frame::XFrame >&              xOwner          );
        static sal_Bool impldbg_checkParameter_dispatch             (   const   css::util::URL&                                         aURL            ,
                                                                        const   css::uno::Sequence< css::beans::PropertyValue >&        seqArguments    );
        static sal_Bool impldbg_checkParameter_addStatusListener    (   const   css::uno::Reference< css::frame::XStatusListener >&     xControl        ,
                                                                        const   css::util::URL&                                         aURL            );
        static sal_Bool impldbg_checkParameter_removeStatusListener (   const   css::uno::Reference< css::frame::XStatusListener >&     xControl        ,
                                                                        const   css::util::URL&                                         aURL            );
    #endif  // #ifdef ENABLE_ASSERTIONS

    //-------------------------------------------------------------------------------------------------------------
    //  variables
    //  (should be private everyway!)
    //-------------------------------------------------------------------------------------------------------------

    private:

        css::uno::WeakReference< css::frame::XFrame >           m_xOwnerWeak        ;   /// css::uno::WeakReference to owner (Don't use a hard css::uno::Reference. Owner can't delete us then!)
        css::uno::Reference< css::lang::XMultiServiceFactory >  m_xFactory          ;   /// factory shared with our owner to create new services!
        IMPL_ListenerHashContainer                              m_aListenerContainer;   /// hash table for listener at specified URLs
        sal_Bool                                                m_bAlreadyDisposed  ;   /// Protection against multiple disposing calls.
        sal_Bool                                                m_bActivateListener ;   /// dispatcher is listener for frame activation
        MenuManager*                                            m_pMenuManager      ;   /// menu manager controlling menu dispatches

};      //  class MenuDispatcher

}       //  namespace framework

#endif  //  #ifndef __FRAMEWORK_DISPATCH_MENUDISPATCHER_HXX_
<commit_msg>INTEGRATION: CWS ooo19126 (1.4.458); FILE MERGED 2005/09/05 13:04:43 rt 1.4.458.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: menudispatcher.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 00:13:58 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

#ifndef __FRAMEWORK_DISPATCH_MENUDISPATCHER_HXX_
#define __FRAMEWORK_DISPATCH_MENUDISPATCHER_HXX_

//_________________________________________________________________________________________________________________
//  my own includes
//_________________________________________________________________________________________________________________

#ifndef __FRAMEWORK_CLASSES_TASKCREATOR_HXX_
#include <classes/taskcreator.hxx>
#endif

#ifndef __FRAMEWORK_SERVICES_FRAME_HXX_
#include <services/frame.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_GENERIC_HXX_
#include <macros/generic.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_XINTERFACE_HXX_
#include <macros/xinterface.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_XTYPEPROVIDER_HXX_
#include <macros/xtypeprovider.hxx>
#endif

#ifndef __FRAMEWORK_MACROS_DEBUG_HXX_
#include <macros/debug.hxx>
#endif

#ifndef __FRAMEWORK_THREADHELP_THREADHELPBASE_HXX_
#include <threadhelp/threadhelpbase.hxx>
#endif

#ifndef __FRAMEWORK_CLASSES_MENUMANAGER_HXX_
#include <classes/menumanager.hxx>
#endif

#ifndef __FRAMEWORK_GENERAL_H_
#include <general.h>
#endif

#ifndef __FRAMEWORK_STDTYPES_H_
#include <stdtypes.h>
#endif

//_________________________________________________________________________________________________________________
//  interface includes
//_________________________________________________________________________________________________________________

#ifndef _COM_SUN_STAR_LANG_XTYPEPROVIDER_HPP_
#include <com/sun/star/lang/XTypeProvider.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_XDISPATCH_HPP_
#include <com/sun/star/frame/XDispatch.hpp>
#endif

#ifndef _COM_SUN_STAR_UTIL_URL_HPP_
#include <com/sun/star/util/URL.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_DISPATCHDESCRIPTOR_HPP_
#include <com/sun/star/frame/DispatchDescriptor.hpp>
#endif

#ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP_
#include <com/sun/star/beans/PropertyValue.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_XSTATUSLISTENER_HPP_
#include <com/sun/star/frame/XStatusListener.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_XFRAMELOADER_HPP_
#include <com/sun/star/frame/XFrameLoader.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_XLOADEVENTLISTENER_HPP_
#include <com/sun/star/frame/XLoadEventListener.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_XDESKTOP_HPP_
#include <com/sun/star/frame/XDesktop.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_FEATURESTATEEVENT_HPP_
#include <com/sun/star/frame/FeatureStateEvent.hpp>
#endif

#ifndef _COM_SUN_STAR_FRAME_XFRAMEACTIONLISTENER_HPP_
#include <com/sun/star/frame/XFrameActionListener.hpp>
#endif

//_________________________________________________________________________________________________________________
//  other includes
//_________________________________________________________________________________________________________________

#ifndef _CPPUHELPER_WEAK_HXX_
#include <cppuhelper/weak.hxx>
#endif

#ifndef _CPPUHELPER_WEAKREF_HXX_
#include <cppuhelper/weakref.hxx>
#endif

#ifndef _CPPUHELPER_INTERFACECONTAINER_H_
#include <cppuhelper/interfacecontainer.h>
#endif

//_________________________________________________________________________________________________________________
//  namespace
//_________________________________________________________________________________________________________________

namespace framework{

//_________________________________________________________________________________________________________________
//  exported const
//_________________________________________________________________________________________________________________

//_________________________________________________________________________________________________________________
//  exported definitions
//_________________________________________________________________________________________________________________

/*-************************************************************************************************************//**
    We must save informations about our listener and URL for listening.
    We implement this as a hashtable for strings.
*//*-*************************************************************************************************************/

typedef ::cppu::OMultiTypeInterfaceContainerHelperVar<  ::rtl::OUString         ,
                                                        OUStringHashCode        ,
                                                        std::equal_to< ::rtl::OUString > > IMPL_ListenerHashContainer;

/*-************************************************************************************************************//**
    @short          helper for desktop only(!) to create new tasks on demand for dispatches
    @descr          Use this class as member only! Never use it as baseclass.
                    XInterface will be ambigous and we hold a weakcss::uno::Reference to ouer OWNER - not to ouer SUPERCLASS!

    @implements     XInterface
                    XDispatch
                    XLoadEventListener
                    XFrameActionListener
                    XEventListener
    @base           ThreadHelpBase
                    OWeakObject

    @devstatus      ready to use
*//*-*************************************************************************************************************/
class MenuDispatcher   :   // interfaces
                                public css::lang::XTypeProvider         ,
                                public css::frame::XDispatch            ,
                                public css::frame::XFrameActionListener ,
                                // baseclasses
                                // Order is neccessary for right initialization!
                                public ThreadHelpBase                       ,
                                public cppu::OWeakObject
{
    //-------------------------------------------------------------------------------------------------------------
    //  public methods
    //-------------------------------------------------------------------------------------------------------------

    public:

        //---------------------------------------------------------------------------------------------------------
        //  constructor / destructor
        //---------------------------------------------------------------------------------------------------------

        /*-****************************************************************************************************//**
            @short      standard ctor
            @descr      These initialize a new instance of ths class with needed informations for work.

            @seealso    using at owner

            @param      "xFactory"  , css::uno::Reference to servicemanager for creation of new services
            @param      "xOwner"    , css::uno::Reference to our owner, the Desktop!!!
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        MenuDispatcher(    const   css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory    ,
                            const   css::uno::Reference< css::frame::XFrame >&              xOwner      );

        //---------------------------------------------------------------------------------------------------------
        //  XInterface
        //---------------------------------------------------------------------------------------------------------

        DECLARE_XINTERFACE
        DECLARE_XTYPEPROVIDER

        //---------------------------------------------------------------------------------------------------------
        //  XDispatch
        //---------------------------------------------------------------------------------------------------------

        /*-****************************************************************************************************//**
            @short      dispatch URL with arguments
            @descr      Every dispatch create a new task. If load of URL failed task will deleted automaticly!

            @seealso    -

            @param      "aURL"          , URL to dispatch.
            @param      "seqArguments"  , list of optional arguments.
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        virtual void SAL_CALL dispatch( const   css::util::URL&                                     aURL            ,
                                        const   css::uno::Sequence< css::beans::PropertyValue >&    seqProperties   ) throw( css::uno::RuntimeException );

        /*-****************************************************************************************************//**
            @short      add listener for state events
            @descr      You can add a listener to get information about status of dispatch: OK or Failed.

            @seealso    method loadFinished()
            @seealso    method loadCancelled()

            @param      "xControl"  , css::uno::Reference to a valid listener for state events.
            @param      "aURL"      , URL about listener will be informed, if something occured.
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        virtual void SAL_CALL addStatusListener(    const   css::uno::Reference< css::frame::XStatusListener >& xControl,
                                                    const   css::util::URL&                                     aURL    ) throw( css::uno::RuntimeException );

        /*-****************************************************************************************************//**
            @short      remove listener for state events
            @descr      You can remove a listener if information of dispatch isn't important for you any longer.

            @seealso    method loadFinished()
            @seealso    method loadCancelled()

            @param      "xControl"  , css::uno::Reference to a valid listener.
            @param      "aURL"      , URL on which listener has registered.
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        virtual void SAL_CALL removeStatusListener( const   css::uno::Reference< css::frame::XStatusListener >& xControl,
                                                    const   css::util::URL&                                     aURL    ) throw( css::uno::RuntimeException );

        //---------------------------------------------------------------------------------------------------------
        //   XFrameActionListener
        //---------------------------------------------------------------------------------------------------------

        virtual void SAL_CALL frameAction( const css::frame::FrameActionEvent& aEvent ) throw ( css::uno::RuntimeException );

        //---------------------------------------------------------------------------------------------------------
        //   XEventListener
        //---------------------------------------------------------------------------------------------------------

        /*-****************************************************************************************************//**
            @short      dispose current instance
            @descr      If service helper isn't required any longer call this method to release all used ressources.

            @seealso    -

            @param      "aEvent", information about source of this event.
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        void SAL_CALL disposing( const EVENTOBJECT& aEvent ) throw( css::uno::RuntimeException );

    //-------------------------------------------------------------------------------------------------------------
    //  protected methods
    //-------------------------------------------------------------------------------------------------------------

    protected:

        /*-****************************************************************************************************//**
            @short      standard destructor
            @descr      This method destruct an instance of this class and clear some member.
                        This method is protected, because its not allowed to use an instance of this class as a member!
                        You MUST use a pointer.

            @seealso    -

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        virtual ~MenuDispatcher();

    //-------------------------------------------------------------------------------------------------------------
    //  private methods
    //-------------------------------------------------------------------------------------------------------------

    private:

        DECL_LINK( Close_Impl, void* );

        /*-****************************************************************************************************//**
            @short      -
            @descr      -

            @seealso    -

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        void impl_sendStatusEvent(  const   css::uno::Reference< XFRAME >&  xEventSource    ,
                                    const   ::rtl::OUString&        sURL            ,
                                            sal_Bool                bLoadState      );

        /*-****************************************************************************************************//**
            @short      -
            @descr      -

            @seealso    -

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        sal_Bool impl_setMenuBar( MenuBar* pMenuBar, sal_Bool bMenuFromResource = sal_False );

        /*-****************************************************************************************************//**
            @short      -
            @descr      -

            @seealso    -

            @param      -
            @return     -

            @onerror    -
        *//*-*****************************************************************************************************/

        void impl_setAccelerators( Menu* pMenu, const Accelerator& aAccel );

    //-------------------------------------------------------------------------------------------------------------
    //  debug methods
    //  (should be private everyway!)
    //-------------------------------------------------------------------------------------------------------------

        /*-****************************************************************************************************//**
            @short      debug-method to check incoming parameter of some other mehods of this class
            @descr      The following methods are used to check parameters for other methods
                        of this class. The return value is used directly for an ASSERT(...).

            @seealso    ASSERTs in implementation!

            @param      css::uno::References to checking variables
            @return     sal_False on invalid parameter<BR>
                        sal_True  otherway

            @onerror    -
        *//*-*****************************************************************************************************/

    #ifdef ENABLE_ASSERTIONS

    private:

        static sal_Bool impldbg_checkParameter_MenuDispatcher      (   const   css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory        ,
                                                                        const   css::uno::Reference< css::frame::XFrame >&              xOwner          );
        static sal_Bool impldbg_checkParameter_dispatch             (   const   css::util::URL&                                         aURL            ,
                                                                        const   css::uno::Sequence< css::beans::PropertyValue >&        seqArguments    );
        static sal_Bool impldbg_checkParameter_addStatusListener    (   const   css::uno::Reference< css::frame::XStatusListener >&     xControl        ,
                                                                        const   css::util::URL&                                         aURL            );
        static sal_Bool impldbg_checkParameter_removeStatusListener (   const   css::uno::Reference< css::frame::XStatusListener >&     xControl        ,
                                                                        const   css::util::URL&                                         aURL            );
    #endif  // #ifdef ENABLE_ASSERTIONS

    //-------------------------------------------------------------------------------------------------------------
    //  variables
    //  (should be private everyway!)
    //-------------------------------------------------------------------------------------------------------------

    private:

        css::uno::WeakReference< css::frame::XFrame >           m_xOwnerWeak        ;   /// css::uno::WeakReference to owner (Don't use a hard css::uno::Reference. Owner can't delete us then!)
        css::uno::Reference< css::lang::XMultiServiceFactory >  m_xFactory          ;   /// factory shared with our owner to create new services!
        IMPL_ListenerHashContainer                              m_aListenerContainer;   /// hash table for listener at specified URLs
        sal_Bool                                                m_bAlreadyDisposed  ;   /// Protection against multiple disposing calls.
        sal_Bool                                                m_bActivateListener ;   /// dispatcher is listener for frame activation
        MenuManager*                                            m_pMenuManager      ;   /// menu manager controlling menu dispatches

};      //  class MenuDispatcher

}       //  namespace framework

#endif  //  #ifndef __FRAMEWORK_DISPATCH_MENUDISPATCHER_HXX_
<|endoftext|>


<commit_before>#include <unit_test.h>
#include <version/version.h>

class VersioningTest : public UnitTest
{
public:
	virtual bool run_tests();

private:
	bool _is_correct_version_tag(const char *version_tag, uint32_t result_goal);
	bool _is_correct_version_tag_vendor(const char *version_tag, uint32_t result_goal);

	bool _test_flight_version();
	bool _test_vendor_version();
};

bool VersioningTest::_is_correct_version_tag(const char *version_tag, uint32_t result_goal)
{
	uint32_t result = version_tag_to_number(version_tag);

	if (result == result_goal) {
		return true;

	} else {
		PX4_ERR("Wrong version: tag: %s, got: 0x%x, expected: 0x%x", version_tag, result, result_goal);
		return false;
	}
}

bool VersioningTest::_is_correct_version_tag_vendor(const char *version_tag, uint32_t result_goal)
{
	uint32_t result = version_tag_to_vendor_version_number(version_tag);

	if (result == result_goal) {
		return true;

	} else {
		PX4_ERR("Wrong version: tag: %s, got: 0x%x, expected: 0x%x", version_tag, result, result_goal);
		return false;
	}
}

bool VersioningTest::run_tests()
{
	ut_run_test(_test_flight_version);
	ut_run_test(_test_vendor_version);

	return (_tests_failed == 0);
}

bool VersioningTest::_test_flight_version()
{
	ut_assert_true(_is_correct_version_tag("v11.45.99-1.2.3", 0xB2D63ff));
	ut_assert_true(_is_correct_version_tag("v1.2.3", 0x010203ff));
	ut_assert_true(_is_correct_version_tag("v255.255.255", 0xffffffff));
	ut_assert_true(_is_correct_version_tag("v255.255.255-11", 0xffffff00));
	ut_assert_true(_is_correct_version_tag("v1.2.3-111", 0x01020300));
	ut_assert_true(_is_correct_version_tag("v1.2.3-11-abababab", 0x01020300));
	ut_assert_true(_is_correct_version_tag("11.45.99-1.2.3", 0x0B2D63ff));
	ut_assert_true(_is_correct_version_tag("v11.45.99-1.2.3rc3-7-g7e282f57", 0x0B2D6300));
	ut_assert_true(_is_correct_version_tag("v11.45.99-1.2.3rc4", 0x0B2D63C0));
	ut_assert_true(_is_correct_version_tag("v11.45.99-1.2.3alpha3-7-g7e282f57", 0x0B2D6300));
	ut_assert_true(_is_correct_version_tag("v11.45.99-1.2.3alpha4", 0x0B2D6340));
	ut_assert_true(_is_correct_version_tag("v11.45.99-1.2.3beta3-7-g7e282f57", 0x0B2D6300));
	ut_assert_true(_is_correct_version_tag("v11.45.99-1.2.3beta4", 0x0B2D6380));
	ut_assert_true(_is_correct_version_tag("v11.45.99-1.2.3dev4", 0x0B2D6300));
	ut_assert_true(_is_correct_version_tag("v11.45.99-1.2.3dev3-7-g7e282f57", 0xB2D6300));
	ut_assert_true(_is_correct_version_tag("0.45.99-1.2.3beta4", 0x002D6380));
	ut_assert_true(_is_correct_version_tag("0.0.0-1.2.3beta4", 0x00000080));
	ut_assert_true(_is_correct_version_tag("0.0.0-1.2.3dev4", 0x00000000));
	ut_assert_true(_is_correct_version_tag("v1.6.2-1.0.0", 0x010602ff));
	ut_assert_true(_is_correct_version_tag("v1.6.2-1.0.0rc2", 0x010602C0));
	ut_assert_true(_is_correct_version_tag("v1.6.2-1.0.0-rc2", 0x010602C0));
	ut_assert_true(_is_correct_version_tag("v1.6.2-1.0.0-rc2-abababab", 0x01060200));
	ut_assert_true(_is_correct_version_tag("v1.6.2-rc2", 0x010602C0));
	ut_assert_true(_is_correct_version_tag("v1.6.2rc1", 0x010602C0));
	ut_assert_true(_is_correct_version_tag("v1.6.10-100-g890c415", 0x01060A00));
	ut_assert_true(_is_correct_version_tag("v1.6.2-0.8.7-67-g1d5e979", 0x01060200));

	return true;
}

bool VersioningTest::_test_vendor_version()
{
	ut_assert_true(_is_correct_version_tag_vendor("alpha", 0x00000000));
	ut_assert_true(_is_correct_version_tag_vendor("alpha23", 0x00000000));
	ut_assert_true(_is_correct_version_tag_vendor("v11.45.99-34.56.88", 0x223858FF));
	ut_assert_true(_is_correct_version_tag_vendor("v11.45.99-1.2.3", 0x010203FF));
	ut_assert_true(_is_correct_version_tag_vendor("1.2.3-11.45.99", 0x0B2D63FF));
	ut_assert_true(_is_correct_version_tag_vendor("v1.6.2-1.0.0", 0x010000FF));
	ut_assert_true(_is_correct_version_tag_vendor("v1.2.3-255.255.255", 0xFFFFFFFF));
	ut_assert_true(_is_correct_version_tag_vendor("v1.2.3-255.255.255-11", 0xFFFFFFFF));
	ut_assert_true(_is_correct_version_tag_vendor("v1.2.3", 0x000000FF));
	ut_assert_true(_is_correct_version_tag_vendor("v1.6.2-rc2", 0x000000C0));
	ut_assert_true(_is_correct_version_tag_vendor("v1.2.3-11", 0x00000000));
	ut_assert_true(_is_correct_version_tag_vendor("v1.2.3-11.45", 0x00000000));
	ut_assert_true(_is_correct_version_tag_vendor("v1.2.3-11-abababab", 0x00000000));
	ut_assert_true(_is_correct_version_tag_vendor("v1.2.3-11.45.99rc3-7-g7e282f57", 0x0B2D6300));
	ut_assert_true(_is_correct_version_tag_vendor("v1.2.3-11.45.99rc4", 0x0B2D63C0));
	ut_assert_true(_is_correct_version_tag_vendor("v1.2.3-11.45.99alpha3-7-g7e282f57", 0x0B2D6300));
	ut_assert_true(_is_correct_version_tag_vendor("v1.2.3-11.45.99alpha4", 0x0B2D6340));
	ut_assert_true(_is_correct_version_tag_vendor("v1.2.3-11.45.99beta3-7-g7e282f57", 0x0B2D6300));
	ut_assert_true(_is_correct_version_tag_vendor("v1.2.3-11.45.99beta4", 0x0B2D6380));
	ut_assert_true(_is_correct_version_tag_vendor("v1.2.3-11.45.99dev4", 0x0B2D6300));
	ut_assert_true(_is_correct_version_tag_vendor("v1.2.3-11.45.99dev3-7-g7e282f57", 0x0B2D6300));
	ut_assert_true(_is_correct_version_tag_vendor("v1.6.2-1.0.0-rc2-abababab", 0x01000000));
	ut_assert_true(_is_correct_version_tag_vendor("v1.6.2-1.0.0-rc2-23-abababab", 0x010000C0));
	ut_assert_true(_is_correct_version_tag_vendor("v1.6.2-0.8.7-67-g1d5e979", 0x00080700));
	ut_assert_true(_is_correct_version_tag_vendor("v1.6.0-100-g890c415", 0x00000000));
	ut_assert_true(_is_correct_version_tag_vendor("1.2.3-0.45.99beta4", 0x002D6380));
	ut_assert_true(_is_correct_version_tag_vendor("1.2.3-0.0.0beta4", 0x00000080));
	ut_assert_true(_is_correct_version_tag_vendor("1.2.3-0.0.0dev4", 0x00000000));

	return true;
}

ut_declare_test_c(test_versioning, VersioningTest);
<commit_msg>versioning: refactor unit tests<commit_after>#include <unit_test.h>
#include <version/version.h>

class VersioningTest : public UnitTest
{
public:
	virtual bool run_tests();

private:
	bool _test_tag_to_version_number(const char *version_tag, uint32_t flight_version_target, uint32_t vendor_version_target);
};

bool VersioningTest::_test_tag_to_version_number(const char *version_tag, uint32_t flight_version_target, uint32_t vendor_version_target)
{
	uint32_t flight_version_result = version_tag_to_number(version_tag);
	uint32_t vendor_version_result = version_tag_to_vendor_version_number(version_tag);

	if (flight_version_target == flight_version_result) {
		if (vendor_version_target == vendor_version_result) {
			return true;
		} else {
			PX4_ERR("Wrong vendor version: tag: %s, got: 0x%x, expected: 0x%x", version_tag, vendor_version_result, vendor_version_target);
			return false;
		}
	} else {
		PX4_ERR("Wrong flight version: tag: %s, got: 0x%x, expected: 0x%x", version_tag, flight_version_result, flight_version_target);
		return false;
	}
}

bool VersioningTest::run_tests()
{
	ut_assert_true(_test_tag_to_version_number("v11.45.99-1.2.3", 					0x0B2D63FF, 0x010203FF));
	ut_assert_true(_test_tag_to_version_number("v11.45.99-01.02.03", 				0x0B2D63FF, 0x010203FF));
	ut_assert_true(_test_tag_to_version_number("v011.045.099-001.002.003", 			0x0B2D63FF, 0x010203FF));
	ut_assert_true(_test_tag_to_version_number("v011.045.099-1.2.3",	 			0x0B2D63FF, 0x010203FF));
	ut_assert_true(_test_tag_to_version_number("v1.2.3", 							0x010203FF, 0x000000FF));
	ut_assert_true(_test_tag_to_version_number("v255.255.255", 						0xFFFFFFFF, 0x000000FF));
	ut_assert_true(_test_tag_to_version_number("v255.255.255-11", 					0xFFFFFF00, 0x00000000));
	ut_assert_true(_test_tag_to_version_number("v255.255.255-255.255.255", 			0xFFFFFFFF, 0xFFFFFFFF));
	ut_assert_true(_test_tag_to_version_number("v255.255.255-0.0.0", 				0xFFFFFFFF, 0x000000FF));
	ut_assert_true(_test_tag_to_version_number("v0.0.0-0.0.0", 						0x000000FF, 0x000000FF));
	ut_assert_true(_test_tag_to_version_number("v0.0.0-255.255.255", 				0x000000FF, 0xFFFFFFFF));
	ut_assert_true(_test_tag_to_version_number("v1.2.3-111", 						0x01020300, 0x00000000));
	ut_assert_true(_test_tag_to_version_number("v1.2.3-11-gabababab", 				0x01020300, 0x00000000));
	ut_assert_true(_test_tag_to_version_number("11.45.99-1.2.3", 					0x0B2D63FF, 0x010203FF));
	ut_assert_true(_test_tag_to_version_number("v11.45.99-1.2.3rc3-7-g7e282f57", 	0x0B2D6300, 0x01020300));
	ut_assert_true(_test_tag_to_version_number("v11.45.99-1.2.3rc4", 				0x0B2D63C0, 0x010203C0));
	ut_assert_true(_test_tag_to_version_number("v11.45.99-1.2.3alpha3-7-g7e282f57", 0x0B2D6300, 0x01020300));
	ut_assert_true(_test_tag_to_version_number("v11.45.99-1.2.3alpha4", 			0x0B2D6340, 0x01020340));
	ut_assert_true(_test_tag_to_version_number("v11.45.99-1.2.3beta3-7-g7e282f57", 	0x0B2D6300, 0x01020300));
	ut_assert_true(_test_tag_to_version_number("v11.45.99-1.2.3beta4", 				0x0B2D6380, 0x01020380));
	ut_assert_true(_test_tag_to_version_number("v11.45.99-1.2.3dev4", 				0x0B2D6300, 0x01020300));
	ut_assert_true(_test_tag_to_version_number("v11.45.99-1.2.3dev3-7-g7e282f57", 	0x0B2D6300, 0x01020300));
	ut_assert_true(_test_tag_to_version_number("0.45.99-1.2.3beta4", 				0x002D6380, 0x01020380));
	ut_assert_true(_test_tag_to_version_number("0.0.0-1.2.3beta4", 					0x00000080, 0x01020380));
	ut_assert_true(_test_tag_to_version_number("0.0.0-1.2.3dev4", 					0x00000000, 0x01020300));
	ut_assert_true(_test_tag_to_version_number("v1.6.2-1.0.0", 						0x010602FF, 0x010000FF));
	ut_assert_true(_test_tag_to_version_number("v1.6.2-1.0.0rc2", 					0x010602C0, 0x010000C0));
	ut_assert_true(_test_tag_to_version_number("v1.6.2-1.0.0-rc2", 					0x010602C0, 0x010000C0));
	ut_assert_true(_test_tag_to_version_number("v1.6.2-1.0.0-rc2-gabababab", 		0x01060200, 0x01000000));
	ut_assert_true(_test_tag_to_version_number("v1.6.2-rc2", 						0x010602C0, 0x000000C0));
	ut_assert_true(_test_tag_to_version_number("v1.6.2rc1", 						0x010602C0, 0x000000C0));
	ut_assert_true(_test_tag_to_version_number("v1.6.10-100-g890c415", 				0x01060A00, 0x00000000));
	ut_assert_true(_test_tag_to_version_number("v1.6.10-99999999999999-g890c415",	0x01060A00, 0x00000000));
	ut_assert_true(_test_tag_to_version_number("v1.6.2-0.8.7-67-g1d5e979", 			0x01060200, 0x00080700));
	ut_assert_true(_test_tag_to_version_number("randomtext", 						0x00000000, 0x00000000));
	ut_assert_true(_test_tag_to_version_number("randomtextwithnumber12", 			0x00000000, 0x00000000));
	ut_assert_true(_test_tag_to_version_number("12randomtextwithnumber", 			0x00000000, 0x00000000));
	ut_assert_true(_test_tag_to_version_number("12.12-randomtextwithnumber", 		0x00000000, 0x00000000));
	ut_assert_true(_test_tag_to_version_number("v12.12-randomtextwithnumber", 		0x00000000, 0x00000000));
	ut_assert_true(_test_tag_to_version_number("...-...", 							0x00000000, 0x00000000));
	ut_assert_true(_test_tag_to_version_number("v...-...", 							0x00000000, 0x00000000));

	return (_tests_failed == 0);
}

ut_declare_test_c(test_versioning, VersioningTest);
<|endoftext|>


<commit_before>/*
 * (C) Copyright 2014 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * 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.
 *
 */

#include "logging.hpp"

#include <sstream>
#include <thread>
#include <sys/time.h>

#include <boost/format.hpp>
#include <boost/log/sinks/text_file_backend.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/sinks.hpp>
#include <boost/log/sources/channel_feature.hpp>
#include <boost/log/sources/channel_logger.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/utility/manipulators/add_value.hpp>

namespace logging = boost::log;
namespace attrs = boost::log::attributes;
namespace src = boost::log::sources;
namespace sinks = boost::log::sinks;
namespace expr = boost::log::expressions;
namespace keywords = boost::log::keywords;

typedef sinks::synchronous_sink< sinks::text_file_backend > sink_t;

namespace kurento
{

/* kurento logging sinks */
boost::shared_ptr< sink_t > system_sink;

static std::string
debug_object (GObject *object)
{
  if (object == NULL) {
    return "";
  }

  if (GST_IS_PAD (object) && GST_OBJECT_NAME (object) ) {
    boost::format fmt ("<%s:%s> ");
    fmt % (GST_OBJECT_PARENT (object) != NULL ? GST_OBJECT_NAME (GST_OBJECT_PARENT (
             object) ) : "''") % GST_OBJECT_NAME (object);
    return fmt.str();
  }

  if (GST_IS_OBJECT (object) && GST_OBJECT_NAME (object) ) {
    boost::format fmt ("<%s> ");
    fmt % GST_OBJECT_NAME (object);
    return fmt.str();
  }

  if (G_IS_OBJECT (object) ) {
    boost::format fmt ("<%s@%p> ");
    fmt %  G_OBJECT_TYPE_NAME (object) % object;
    return fmt.str();
  }

  boost::format fmt ("<%p> ");
  fmt % object;
  return fmt.str();
}

static std::string
expand_string (std::string str, int len)
{
  std::string ret = str;
  int sp = len - str.size ();

  for (int i = sp; i > 0; i--) {
    str.append (" ");
  }

  return str;
}

#define LOG expand_string(category->name, 25) << " " <<  \
    boost::filesystem::path(file).filename().string() \
    << ":" << line << " " << function << "() " << \
    debug_object(object) << \
    gst_debug_message_get(message)

static std::string
getDateTime ()
{
  timeval curTime;
  struct tm *timeinfo;
  char buffer[22];

  gettimeofday (&curTime, NULL);;
  timeinfo = localtime (&curTime.tv_sec);

  strftime (buffer, 22, "%Y-%m-%d %H:%M:%S", timeinfo);
  std::string datetime (buffer);
  datetime.append (".");

  std::string micros = std::to_string (curTime.tv_usec);

  while (micros.size() < 6) {
    micros = "0" + micros;
  }

  datetime.append (micros);
  return datetime;
}

void
simple_log_function (GstDebugCategory *category, GstDebugLevel level,
                     const gchar *file,
                     const gchar *function, gint line, GObject *object,
                     GstDebugMessage *message, gpointer user_data)
{
  std::stringstream ss;

  if (level > gst_debug_category_get_threshold (category) ) {
    return;
  }

  ss << getDateTime() << " ";
  ss << getpid() << " ";
  ss << "[" << std::this_thread::get_id () << "]";

  switch (level) {
  case GST_LEVEL_ERROR:
    ss << "   error ";
    break;

  case GST_LEVEL_WARNING:
    ss << " warning ";
    break;

  case GST_LEVEL_FIXME:
    ss << "   fixme ";
    break;

  case GST_LEVEL_INFO:
    ss << "    info ";
    break;

  case GST_LEVEL_DEBUG:
    ss << "   debug ";
    break;

  case GST_LEVEL_LOG:
    ss << "     log ";
    break;

  case GST_LEVEL_TRACE:
    ss << "   trace ";
    break;

  default:
    return;
  }

  ss << LOG << std::endl;

  std::cout << ss.str();
  std::cout.flush ();
}

static severity_level
gst_debug_level_to_severity_level (GstDebugLevel level)
{
  switch (level) {
  case GST_LEVEL_ERROR:
    return error;

  case GST_LEVEL_WARNING:
    return warning;

  case GST_LEVEL_FIXME:
    return fixme;

  case GST_LEVEL_INFO:
    return info;

  case GST_LEVEL_DEBUG:
    return debug;

  case GST_LEVEL_LOG:
    return log;

  case GST_LEVEL_TRACE:
    return trace;

  default:
    return undefined;
  }
}

static void
kms_log_function (GstDebugCategory *category, GstDebugLevel level,
                  const gchar *file,
                  const gchar *function, gint line, GObject *object,
                  GstDebugMessage *message, gpointer user_data)
{
  if (level > gst_debug_category_get_threshold (category) ) {
    return;
  }

  severity_level severity = gst_debug_level_to_severity_level (level);

  if (severity == undefined) {
    return;
  }

  BOOST_LOG_SEV (system_logger::get(), severity) <<
      logging::add_value ("Category", expand_string (category->name, 25) ) <<
      logging::add_value ("FileName",
                          boost::filesystem::path (file).filename().string() ) <<
      logging::add_value ("Line", line) <<
      logging::add_value ("Function", function) <<
      logging::add_value ("GObject", debug_object (object) ) <<
      gst_debug_message_get (message);
}

void init_file_collecting (boost::shared_ptr< sink_t > sink,
                           const std::string &path)
{
  sink->locked_backend()->set_file_collector (sinks::file::make_collector (
        keywords::target = path,
        keywords::max_size = 16 * 1024 * 1024,
        keywords::min_free_space = 100 * 1024 * 1024
      ) );
}

static std::string
severity_to_string (severity_level level)
{
  switch (level) {
  case error:
    return "  error";

  case warning:
    return "warning";

  case fixme:
    return "  fixme";

  case info:
    return "   info";

  case debug:
    return "  debug";

  case log:
    return "    log";

  case trace:
    return "  trace";

  default:
    return "unknown";
  }
}

static void
system_formatter (logging::record_view const &rec,
                  logging::formatting_ostream &strm)
{
  logging::value_ref< severity_level > val =
    logging::extract< severity_level > ("Severity", rec);
  auto date_time_formatter = expr::stream
                             << expr::format_date_time< boost::posix_time::ptime > ("TimeStamp",
                                 "%Y-%m-%d %H:%M:%S,%f");

  date_time_formatter (rec, strm) << " ";
  strm << logging::extract< attrs::current_process_id::value_type > ("ProcessID",
       rec) << " ";
  strm << "[" <<
       logging::extract< attrs::current_thread_id::value_type > ("ThreadID",
           rec) << "] ";
  strm << severity_to_string (val.get() ) << " ";
  strm << logging::extract< std::string > ("Category", rec) << " ";
  strm << logging::extract< std::string > ("FileName", rec) << ":";
  strm << logging::extract< int > ("Line", rec) << " ";
  strm << logging::extract< std::string > ("Function", rec) << "() ";
  strm << logging::extract< std::string > ("GObject", rec) << " ";
  strm << rec[expr::smessage];
}

bool
kms_init_logging (const std::string &path)
{
  gst_debug_remove_log_function_by_data (NULL);
  gst_debug_add_log_function (kms_log_function, NULL, NULL);

  boost::shared_ptr< logging::core > core = logging::core::get();

  boost::shared_ptr< sinks::text_file_backend > backend =
    boost::make_shared< sinks::text_file_backend > (
      keywords::file_name = path + "/" + "%Y%m%d_%H%M%S_%5N.log",
      keywords::rotation_size = 5 * 1024 * 1024,
      keywords::time_based_rotation = sinks::file::rotation_at_time_point (12, 0, 0)
    );

  /* Enable auto-flushing after each log record written */
  backend->auto_flush (true);

  /* Wrap it into the frontend and register in the core.   */
  /* The backend requires synchronization in the frontend. */
  system_sink = boost::shared_ptr< sink_t > (new sink_t (backend) );

  /*Set up filter to pass only records that have the necessary attributes */
  system_sink->set_filter (
    expr::has_attr< std::string > ("Channel") &&
    expr::attr< std::string > ("Channel") == "system"
  );

  /* Set up where the rotated files will be stored */
  init_file_collecting (system_sink, path + "/logs");

  /* Upon restart, scan the directory for files matching the file_name pattern */
  system_sink->locked_backend()->scan_for_files();

  core->add_sink (system_sink);

  system_sink->set_formatter (&system_formatter);

  return true;
}

}  /* kurento */
<commit_msg>logging: Use formatting logic for the severity level<commit_after>/*
 * (C) Copyright 2014 Kurento (http://kurento.org/)
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl-2.1.html
 *
 * 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.
 *
 */

#include "logging.hpp"

#include <sstream>
#include <thread>
#include <sys/time.h>

#include <boost/format.hpp>
#include <boost/log/sinks/text_file_backend.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/sinks.hpp>
#include <boost/log/sources/channel_feature.hpp>
#include <boost/log/sources/channel_logger.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/utility/manipulators/add_value.hpp>

namespace logging = boost::log;
namespace attrs = boost::log::attributes;
namespace src = boost::log::sources;
namespace sinks = boost::log::sinks;
namespace expr = boost::log::expressions;
namespace keywords = boost::log::keywords;

typedef sinks::synchronous_sink< sinks::text_file_backend > sink_t;

namespace kurento
{

/* kurento logging sinks */
boost::shared_ptr< sink_t > system_sink;

static std::string
debug_object (GObject *object)
{
  if (object == NULL) {
    return "";
  }

  if (GST_IS_PAD (object) && GST_OBJECT_NAME (object) ) {
    boost::format fmt ("<%s:%s> ");
    fmt % (GST_OBJECT_PARENT (object) != NULL ? GST_OBJECT_NAME (GST_OBJECT_PARENT (
             object) ) : "''") % GST_OBJECT_NAME (object);
    return fmt.str();
  }

  if (GST_IS_OBJECT (object) && GST_OBJECT_NAME (object) ) {
    boost::format fmt ("<%s> ");
    fmt % GST_OBJECT_NAME (object);
    return fmt.str();
  }

  if (G_IS_OBJECT (object) ) {
    boost::format fmt ("<%s@%p> ");
    fmt %  G_OBJECT_TYPE_NAME (object) % object;
    return fmt.str();
  }

  boost::format fmt ("<%p> ");
  fmt % object;
  return fmt.str();
}

static std::string
expand_string (std::string str, int len)
{
  std::string ret = str;
  int sp = len - str.size ();

  for (int i = sp; i > 0; i--) {
    str.append (" ");
  }

  return str;
}

#define LOG expand_string(category->name, 25) << " " <<  \
    boost::filesystem::path(file).filename().string() \
    << ":" << line << " " << function << "() " << \
    debug_object(object) << \
    gst_debug_message_get(message)

static std::string
getDateTime ()
{
  timeval curTime;
  struct tm *timeinfo;
  char buffer[22];

  gettimeofday (&curTime, NULL);;
  timeinfo = localtime (&curTime.tv_sec);

  strftime (buffer, 22, "%Y-%m-%d %H:%M:%S", timeinfo);
  std::string datetime (buffer);
  datetime.append (".");

  std::string micros = std::to_string (curTime.tv_usec);

  while (micros.size() < 6) {
    micros = "0" + micros;
  }

  datetime.append (micros);
  return datetime;
}

void
simple_log_function (GstDebugCategory *category, GstDebugLevel level,
                     const gchar *file,
                     const gchar *function, gint line, GObject *object,
                     GstDebugMessage *message, gpointer user_data)
{
  std::stringstream ss;

  if (level > gst_debug_category_get_threshold (category) ) {
    return;
  }

  ss << getDateTime() << " ";
  ss << getpid() << " ";
  ss << "[" << std::this_thread::get_id () << "]";

  switch (level) {
  case GST_LEVEL_ERROR:
    ss << "   error ";
    break;

  case GST_LEVEL_WARNING:
    ss << " warning ";
    break;

  case GST_LEVEL_FIXME:
    ss << "   fixme ";
    break;

  case GST_LEVEL_INFO:
    ss << "    info ";
    break;

  case GST_LEVEL_DEBUG:
    ss << "   debug ";
    break;

  case GST_LEVEL_LOG:
    ss << "     log ";
    break;

  case GST_LEVEL_TRACE:
    ss << "   trace ";
    break;

  default:
    return;
  }

  ss << LOG << std::endl;

  std::cout << ss.str();
  std::cout.flush ();
}

static severity_level
gst_debug_level_to_severity_level (GstDebugLevel level)
{
  switch (level) {
  case GST_LEVEL_ERROR:
    return error;

  case GST_LEVEL_WARNING:
    return warning;

  case GST_LEVEL_FIXME:
    return fixme;

  case GST_LEVEL_INFO:
    return info;

  case GST_LEVEL_DEBUG:
    return debug;

  case GST_LEVEL_LOG:
    return log;

  case GST_LEVEL_TRACE:
    return trace;

  default:
    return undefined;
  }
}

static void
kms_log_function (GstDebugCategory *category, GstDebugLevel level,
                  const gchar *file,
                  const gchar *function, gint line, GObject *object,
                  GstDebugMessage *message, gpointer user_data)
{
  if (level > gst_debug_category_get_threshold (category) ) {
    return;
  }

  severity_level severity = gst_debug_level_to_severity_level (level);

  if (severity == undefined) {
    return;
  }

  BOOST_LOG_SEV (system_logger::get(), severity) <<
      logging::add_value ("Category", expand_string (category->name, 25) ) <<
      logging::add_value ("FileName",
                          boost::filesystem::path (file).filename().string() ) <<
      logging::add_value ("Line", line) <<
      logging::add_value ("Function", function) <<
      logging::add_value ("GObject", debug_object (object) ) <<
      gst_debug_message_get (message);
}

void init_file_collecting (boost::shared_ptr< sink_t > sink,
                           const std::string &path)
{
  sink->locked_backend()->set_file_collector (sinks::file::make_collector (
        keywords::target = path,
        keywords::max_size = 16 * 1024 * 1024,
        keywords::min_free_space = 100 * 1024 * 1024
      ) );
}

/* The formatting logic for the severity level */
template< typename CharT, typename TraitsT >
inline std::basic_ostream< CharT, TraitsT > &operator<< (
  std::basic_ostream< CharT, TraitsT > &strm, severity_level lvl)
{
  static const char *const str[] = {
    "error",
    "warning",
    "fixme",
    "info",
    "debug",
    "log",
    "trace",
    "unknown"
  };

  if (static_cast< std::size_t > (lvl) < (sizeof (str) / sizeof (*str) ) ) {
    strm << str[lvl];
  } else {
    strm << static_cast< int > (lvl);
  }

  return strm;
}

static void
system_formatter (logging::record_view const &rec,
                  logging::formatting_ostream &strm)
{
  auto date_time_formatter = expr::stream
                             << expr::format_date_time< boost::posix_time::ptime > ("TimeStamp",
                                 "%Y-%m-%d %H:%M:%S,%f");
  date_time_formatter (rec, strm) << " ";
  strm << logging::extract< attrs::current_process_id::value_type > ("ProcessID",
       rec) << " ";
  strm << "[" <<
       logging::extract< attrs::current_thread_id::value_type > ("ThreadID",
           rec) << "] ";
  strm << logging::extract< severity_level > ("Severity", rec) << " ";
  strm << logging::extract< std::string > ("Category", rec) << " ";
  strm << logging::extract< std::string > ("FileName", rec) << ":";
  strm << logging::extract< int > ("Line", rec) << " ";
  strm << logging::extract< std::string > ("Function", rec) << "() ";
  strm << logging::extract< std::string > ("GObject", rec) << " ";
  strm << rec[expr::smessage];
}

bool
kms_init_logging (const std::string &path)
{
  gst_debug_remove_log_function_by_data (NULL);
  gst_debug_add_log_function (kms_log_function, NULL, NULL);

  boost::shared_ptr< logging::core > core = logging::core::get();

  boost::shared_ptr< sinks::text_file_backend > backend =
    boost::make_shared< sinks::text_file_backend > (
      keywords::file_name = path + "/" + "%Y%m%d_%H%M%S_%5N.log",
      keywords::rotation_size = 5 * 1024 * 1024,
      keywords::time_based_rotation = sinks::file::rotation_at_time_point (12, 0, 0)
    );

  /* Enable auto-flushing after each log record written */
  backend->auto_flush (true);

  /* Wrap it into the frontend and register in the core.   */
  /* The backend requires synchronization in the frontend. */
  system_sink = boost::shared_ptr< sink_t > (new sink_t (backend) );

  /*Set up filter to pass only records that have the necessary attributes */
  system_sink->set_filter (
    expr::has_attr< std::string > ("Channel") &&
    expr::attr< std::string > ("Channel") == "system"
  );

  /* Set up where the rotated files will be stored */
  init_file_collecting (system_sink, path + "/logs");

  /* Upon restart, scan the directory for files matching the file_name pattern */
  system_sink->locked_backend()->scan_for_files();

  core->add_sink (system_sink);

  system_sink->set_formatter (&system_formatter);

  return true;
}

}  /* kurento */
<|endoftext|>


<commit_before>/*
 * This file is part of the Polkit-qt project
 * Copyright (C) 2009 Daniel Nicoletti <dantti85-pk@yahoo.com.br>
 * Copyright (C) 2009 Dario Freddi <drf54321@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB. If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "context.h"

#include "singleton.h"

#include <QtCore/QSocketNotifier>
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QStringList>
#include <QtDBus/QDBusInterface>
#include <QtDBus/QDBusReply>

#include <polkit-dbus/polkit-dbus.h>

using namespace QPolicyKit;

class ContextHelper
{
public:
    ContextHelper() : q(0) {}
    ~ContextHelper() {
        delete q;
    }
    Context *q;
};

POLKIT_QT_GLOBAL_STATIC(ContextHelper, s_globalContext)

Context *Context::instance()
{
    if (!s_globalContext->q) {
        new Context;
    }

    return s_globalContext->q;
}

class Context::Private
{
    public:
        // I'm using null instead of 0 as polkit will return
        // NULL on failures
        Private() : pkContext(NULL)
        , pkTracker(NULL)
        , m_hasError(false)
        {};

        void init();

        PolKitContext *pkContext;
        PolKitTracker *pkTracker;
        bool m_hasError;
        QString m_lastError;
        DBusConnection *m_systemBus;

        QMap<int, QSocketNotifier*> m_watches;

        static int  io_add_watch(PolKitContext *context, int fd);
        static void io_remove_watch(PolKitContext *context, int fd);
        static void pk_config_changed(PolKitContext *context, void *user_data);

        QDomDocument introspect(const QString &service, const QString &path, const QDBusConnection &c);
        QStringList getSignals(const QDomDocument &iface);
};

Context::Context(QObject *parent)
 : QObject(parent)
 , d(new Private())
{
    Q_ASSERT(!s_globalContext->q);
    s_globalContext->q = this;

    qDebug() << "Context - Constructing singleton";
    d->init();
}

Context::~Context()
{
    if (d->pkContext != NULL) {
        polkit_context_unref(d->pkContext);
    }
    if (d->pkTracker != NULL) {
        polkit_tracker_unref(d->pkTracker);
    }

    delete d;
}

void Context::Private::init()
{
    DBusError error;
    DBusError dbus_error;
    PolKitError *pk_error;
    dbus_error_init(&error);
    //         if ((_singleton->priv->system_bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, error)) == NULL) {
    //                 goto error;
    //         }

    if ((m_systemBus = dbus_bus_get(DBUS_BUS_SYSTEM, &error )) == NULL) {
        qWarning() << "Failed to initialize DBus";
    }

    pkContext = polkit_context_new ();
    polkit_context_set_io_watch_functions (pkContext, io_add_watch, io_remove_watch);
    polkit_context_set_config_changed (pkContext, pk_config_changed, Context::instance());

    pk_error = NULL;
    if (!polkit_context_init (pkContext, &pk_error)) {
        qWarning() << "Failed to initialize PolicyKit context: " << polkit_error_get_error_message (pk_error);
        m_lastError = polkit_error_get_error_message (pk_error);
        m_hasError  = true;
        if (pkContext != NULL) {
            polkit_context_unref(pkContext);
        }
        polkit_error_free (pk_error);
        return;
    }
    /* TODO FIXME: I'm pretty sure dbus-glib blows in a way that
     * we can't say we're interested in all signals from all
     * members on all interfaces for a given service... So we do
     * this..
     */

    dbus_error_init (&dbus_error);
    //
    /* need to listen to NameOwnerChanged */
    //         dbus_bus_add_match (m_systemBus,
    //                             "type='signal'"
    //                             ",interface='"DBUS_INTERFACE_DBUS"'"
    //                             ",sender='"DBUS_SERVICE_DBUS"'"
    //                             ",member='NameOwnerChanged'",
    //                             &dbus_error);
    if (QDBusConnection::systemBus().connect( DBUS_SERVICE_DBUS, QString(), DBUS_INTERFACE_DBUS, "NameOwnerChanged",
                                              Context::instance(), SLOT(dbusFilter(const QDBusMessage &)))) {
        qWarning() << "---------------------OK";
    } else {
        qWarning() << "---------------------not Ok";
    }

    //         if (dbus_error_is_set (&dbus_error)) {
    // //                 dbus_set_g_error (error, &dbus_error);
    //                 dbus_error_free (&dbus_error);
    //                 m_hasError  = true;
    //                 qWarning() << "Failed to initialize NameOwnerChanged";
    //                 return;
    // //                 goto error;
    //         }
    //

    // Ok, let's get what we need here

    QStringList sigs;

    sigs += getSignals(introspect("org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Manager", QDBusConnection::systemBus()));
    sigs += getSignals(introspect("org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Session1", QDBusConnection::systemBus()));
    sigs += getSignals(introspect("org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Seat1", QDBusConnection::systemBus()));

    foreach (const QString &sig, sigs) {

        if (QDBusConnection::systemBus().connect("org.freedesktop.ConsoleKit", QString(), QString(),
                                                 sig, Context::instance(), SLOT(dbusFilter(const QDBusMessage &)))) {
            qWarning() << "---------------------OK";
        } else {
            qWarning() << "---------------------not Ok";
        }

    }
    /* need to listen to ConsoleKit signals */
//         dbus_bus_add_match (m_systemBus,
//                             "type='signal',sender='org.freedesktop.ConsoleKit'",
//                             &dbus_error);
//
        if (dbus_error_is_set (&dbus_error)) {
//                 dbus_set_g_error (error, &dbus_error);
                dbus_error_free (&dbus_error);
                qWarning() << "Failed to initialize ConsoleKit";
                m_hasError  = true;
                return;
        }
//
//         if (!dbus_connection_add_filter (m_systemBus,
//                                          filter,
//                                          this,
//                                          NULL)) {
// //                 *error = g_error_new_literal (POLKIT_GNOME_CONTEXT_ERROR,
// //                                               POLKIT_GNOME_CONTEXT_ERROR_FAILED,
// //                                               "Cannot add D-Bus filter");
// //                 goto error;
// qWarning() << "Failed to dbus_connection_add_filter";
//                 m_hasError  = true;
//                 return;
//         }

//     DBusConnection *con;

//     con = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error);
    pkTracker = polkit_tracker_new();
    polkit_tracker_set_system_bus_connection(pkTracker, m_systemBus);

    if (dbus_error_is_set (&dbus_error)) {
        m_hasError  = true;
        m_lastError = QString("DBus error name: %1. message: %2").arg(dbus_error.name).arg(dbus_error.message);
        if (pkContext != NULL) {
            polkit_context_unref(pkContext);
        }
        if (pkTracker != NULL) {
            polkit_tracker_unref(pkTracker);
        }

        dbus_error_free (&dbus_error);
        return;
    }
    polkit_tracker_init (pkTracker);
    m_lastError.clear();
    m_hasError = false;
}

void Context::dbusFilter(const QDBusMessage &message)
{
    qDebug() << "=============================================" << message.service();

qDebug() << message.path();
qDebug() << message.interface() << DBUS_INTERFACE_DBUS;
qDebug() << message.member();

    // forward only NameOwnerChanged and ConsoleKit signals to PolkitTracker
    if ((message.type()        == QDBusMessage::SignalMessage
        && message.interface() == "org.freedesktop.DBus"
        && message.member()    == "NameOwnerChanged")
        || (!message.interface().isEmpty()
        && message.interface().startsWith(QLatin1String("org.freedesktop.ConsoleKit"))) ) {
        qDebug() << "inside";
        DBusMessage *msg = 0;
        DBusMessageIter args;
        msg = dbus_message_new_signal(
                message.path().toUtf8().data(), message.interface().toUtf8().data(),
                message.member().toUtf8().data());
        dbus_message_iter_init_append(msg, &args);
        foreach (QVariant arg, message.arguments()) {
            char *argument = qstrdup(arg.toString().toAscii());

            qDebug() << "First loop in" << argument;
            qDebug() << strlen(argument);

            switch (arg.type()) {
                case QVariant::String:
                    if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, (void*)argument)) {
                        qFatal("Out Of Memory!");
                        exit(1);
                    }
                    break;
                case QVariant::Bool:
                    if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, qstrdup(arg.toString().toAscii()))) {
                        qFatal("Out Of Memory!");
                        exit(1);
                    }
                    break;
                default:
                    qDebug() << "Crap!!";
                    break;
            }

        }
        qDebug() << "dbus_message_get_type() " <<  dbus_message_get_type (msg);
        qDebug() << "dbus_message_get_interface() " << dbus_message_get_interface (msg);
        qDebug() << "dbus_message_get_member() " << dbus_message_get_member (msg);
        qDebug() << "dbus_message_get_signature() " << dbus_message_get_signature (msg);
       qDebug() << "QT dbus_message_get_signature() " << message.signature();

       // WE NEED TO set the msg signature to "s" quite simple but
       // even QDbusMessage don't allow us to do that so...
       // i guess we need to get back and use
       // std DBus
        if (msg && polkit_tracker_dbus_func(d->pkTracker, msg)) {
        //THIS is getting emmited but there's a warning... and i hate
        // warnings :D
            qDebug() << "++++++++++++++++++++++ EMIT CONSOLE_KIT_DB_CHANGED";
            emit consoleKitDBChanged();
        }
    }
    qDebug() << "====================END======================" << message.service();
}

bool Context::hasError()
{
    if (d->m_hasError) {
        // try init again maybe something get
        // back to normal (as DBus might restarted, crashed...)
        d->init();
    }
    return d->m_hasError;
}

QString Context::lastError() const
{
    return d->m_lastError;
}

int Context::Private::io_add_watch(PolKitContext *context, int fd)
{
    qDebug() << "add_watch" << context << fd;

    QSocketNotifier *notify = new QSocketNotifier(fd, QSocketNotifier::Read, Context::instance());
    Context::instance()->d->m_watches[fd] = notify;
    notify->connect(notify, SIGNAL(activated(int)), Context::instance(), SLOT(watchActivatedContext(int)));

    return fd; // use simply the fd as the unique id for the watch
}

void Context::watchActivatedContext(int fd)
{
    Q_ASSERT(d->m_watches.contains(fd));

//    kDebug() << "watchActivated" << fd;

    polkit_context_io_func(d->pkContext, fd);
}

void Context::Private::io_remove_watch(PolKitContext *context, int id)
{
    Q_ASSERT(id > 0);
    qDebug() << "remove_watch" << context << id;
    if (!Context::instance()->d->m_watches.contains(id))
        return; // policykit likes to do this more than once

    QSocketNotifier *notify = Context::instance()->d->m_watches.take(id);
    notify->deleteLater();
    notify->setEnabled(false);
}

void Context::Private::pk_config_changed(PolKitContext *context, void *user_data)
{
    Q_UNUSED(context);
    Q_UNUSED(user_data);
    qDebug() << "PolicyKit reports that the config have changed";
    emit Context::instance()->configChanged();
}

QDomDocument Context::Private::introspect(const QString &service, const QString &path, const QDBusConnection &c)
{
    QDomDocument doc;

    QDBusInterface iface(service, path, "org.freedesktop.DBus.Introspectable", c);
    if (!iface.isValid()) {
        QDBusError err(iface.lastError());
        qDebug() << QString("Cannot introspect object %1 at %2:\n  %3 (%4)\n").arg(path).arg(
                      service).arg(err.name()).arg(err.message());
        return doc;
    }

    QDBusReply<QString> xml = iface.call("Introspect");

    if (!xml.isValid()) {
        QDBusError err(xml.error());
        if (err.isValid()) {
            qDebug() << QString("Call to object %1 at %2:\n  %3 (%4) failed\n").arg(
                        path).arg(service).arg(err.name()).arg(err.message());
        } else {
            qDebug() << QString("Invalid XML received from object %1 at %2\n").arg(
                    path).arg(service);
        }
        return doc;
    }

    doc.setContent(xml);
    return doc;
}

QStringList Context::Private::getSignals(const QDomDocument &doc)
{
    QStringList retlist;

    QDomElement node = doc.documentElement();
    QDomElement child = node.firstChildElement();

    while (!child.isNull()) {
        if (child.tagName() == QLatin1String("node") || child.tagName() == QLatin1String("interface")) {
            QDomElement iface = child.firstChildElement();
            while (!iface.isNull()) {
                if (iface.tagName() == QLatin1String("signal")) {
                    qDebug() << "Found signal: " << iface.attribute("name");
                    retlist.append(iface.attribute("name"));
                }
                iface = iface.nextSiblingElement();
            }
        }

        child = child.nextSiblingElement();
    }

    return retlist;
}

PolKitContext *Context::getPolKitContext()
{
    return d->pkContext;
}

PolKitTracker *Context::getPolKitTracker()
{
    return d->pkTracker;
}
<commit_msg>And it was so easy... but proper documentation could have been better<commit_after>/*
 * This file is part of the Polkit-qt project
 * Copyright (C) 2009 Daniel Nicoletti <dantti85-pk@yahoo.com.br>
 * Copyright (C) 2009 Dario Freddi <drf54321@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB. If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "context.h"

#include "singleton.h"

#include <QtCore/QSocketNotifier>
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QStringList>
#include <QtDBus/QDBusInterface>
#include <QtDBus/QDBusReply>

#include <polkit-dbus/polkit-dbus.h>

using namespace QPolicyKit;

class ContextHelper
{
public:
    ContextHelper() : q(0) {}
    ~ContextHelper() {
        delete q;
    }
    Context *q;
};

POLKIT_QT_GLOBAL_STATIC(ContextHelper, s_globalContext)

Context *Context::instance()
{
    if (!s_globalContext->q) {
        new Context;
    }

    return s_globalContext->q;
}

class Context::Private
{
    public:
        // I'm using null instead of 0 as polkit will return
        // NULL on failures
        Private() : pkContext(NULL)
        , pkTracker(NULL)
        , m_hasError(false)
        {};

        void init();

        PolKitContext *pkContext;
        PolKitTracker *pkTracker;
        bool m_hasError;
        QString m_lastError;
        DBusConnection *m_systemBus;

        QMap<int, QSocketNotifier*> m_watches;

        static int  io_add_watch(PolKitContext *context, int fd);
        static void io_remove_watch(PolKitContext *context, int fd);
        static void pk_config_changed(PolKitContext *context, void *user_data);

        QDomDocument introspect(const QString &service, const QString &path, const QDBusConnection &c);
        QStringList getSignals(const QDomDocument &iface);
};

Context::Context(QObject *parent)
 : QObject(parent)
 , d(new Private())
{
    Q_ASSERT(!s_globalContext->q);
    s_globalContext->q = this;

    qDebug() << "Context - Constructing singleton";
    d->init();
}

Context::~Context()
{
    if (d->pkContext != NULL) {
        polkit_context_unref(d->pkContext);
    }
    if (d->pkTracker != NULL) {
        polkit_tracker_unref(d->pkTracker);
    }

    delete d;
}

void Context::Private::init()
{
    DBusError error;
    DBusError dbus_error;
    PolKitError *pk_error;
    dbus_error_init(&error);
    //         if ((_singleton->priv->system_bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, error)) == NULL) {
    //                 goto error;
    //         }

    if ((m_systemBus = dbus_bus_get(DBUS_BUS_SYSTEM, &error )) == NULL) {
        qWarning() << "Failed to initialize DBus";
    }

    pkContext = polkit_context_new ();
    polkit_context_set_io_watch_functions (pkContext, io_add_watch, io_remove_watch);
    polkit_context_set_config_changed (pkContext, pk_config_changed, Context::instance());

    pk_error = NULL;
    if (!polkit_context_init (pkContext, &pk_error)) {
        qWarning() << "Failed to initialize PolicyKit context: " << polkit_error_get_error_message (pk_error);
        m_lastError = polkit_error_get_error_message (pk_error);
        m_hasError  = true;
        if (pkContext != NULL) {
            polkit_context_unref(pkContext);
        }
        polkit_error_free (pk_error);
        return;
    }
    /* TODO FIXME: I'm pretty sure dbus-glib blows in a way that
     * we can't say we're interested in all signals from all
     * members on all interfaces for a given service... So we do
     * this..
     */

    dbus_error_init (&dbus_error);
    //
    /* need to listen to NameOwnerChanged */
    //         dbus_bus_add_match (m_systemBus,
    //                             "type='signal'"
    //                             ",interface='"DBUS_INTERFACE_DBUS"'"
    //                             ",sender='"DBUS_SERVICE_DBUS"'"
    //                             ",member='NameOwnerChanged'",
    //                             &dbus_error);
    if (QDBusConnection::systemBus().connect( DBUS_SERVICE_DBUS, QString(), DBUS_INTERFACE_DBUS, "NameOwnerChanged",
                                              Context::instance(), SLOT(dbusFilter(const QDBusMessage &)))) {
        qWarning() << "---------------------OK";
    } else {
        qWarning() << "---------------------not Ok";
    }

    //         if (dbus_error_is_set (&dbus_error)) {
    // //                 dbus_set_g_error (error, &dbus_error);
    //                 dbus_error_free (&dbus_error);
    //                 m_hasError  = true;
    //                 qWarning() << "Failed to initialize NameOwnerChanged";
    //                 return;
    // //                 goto error;
    //         }
    //

    // Ok, let's get what we need here

    QStringList sigs;

    sigs += getSignals(introspect("org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Manager", QDBusConnection::systemBus()));
    sigs += getSignals(introspect("org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Session1", QDBusConnection::systemBus()));
    sigs += getSignals(introspect("org.freedesktop.ConsoleKit", "/org/freedesktop/ConsoleKit/Seat1", QDBusConnection::systemBus()));

    foreach (const QString &sig, sigs) {

        if (QDBusConnection::systemBus().connect("org.freedesktop.ConsoleKit", QString(), QString(),
                                                 sig, Context::instance(), SLOT(dbusFilter(const QDBusMessage &)))) {
            qWarning() << "---------------------OK";
        } else {
            qWarning() << "---------------------not Ok";
        }

    }
    /* need to listen to ConsoleKit signals */
//         dbus_bus_add_match (m_systemBus,
//                             "type='signal',sender='org.freedesktop.ConsoleKit'",
//                             &dbus_error);
//
        if (dbus_error_is_set (&dbus_error)) {
//                 dbus_set_g_error (error, &dbus_error);
                dbus_error_free (&dbus_error);
                qWarning() << "Failed to initialize ConsoleKit";
                m_hasError  = true;
                return;
        }
//
//         if (!dbus_connection_add_filter (m_systemBus,
//                                          filter,
//                                          this,
//                                          NULL)) {
// //                 *error = g_error_new_literal (POLKIT_GNOME_CONTEXT_ERROR,
// //                                               POLKIT_GNOME_CONTEXT_ERROR_FAILED,
// //                                               "Cannot add D-Bus filter");
// //                 goto error;
// qWarning() << "Failed to dbus_connection_add_filter";
//                 m_hasError  = true;
//                 return;
//         }

//     DBusConnection *con;

//     con = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error);
    pkTracker = polkit_tracker_new();
    polkit_tracker_set_system_bus_connection(pkTracker, m_systemBus);

    if (dbus_error_is_set (&dbus_error)) {
        m_hasError  = true;
        m_lastError = QString("DBus error name: %1. message: %2").arg(dbus_error.name).arg(dbus_error.message);
        if (pkContext != NULL) {
            polkit_context_unref(pkContext);
        }
        if (pkTracker != NULL) {
            polkit_tracker_unref(pkTracker);
        }

        dbus_error_free (&dbus_error);
        return;
    }
    polkit_tracker_init (pkTracker);
    m_lastError.clear();
    m_hasError = false;
}

void Context::dbusFilter(const QDBusMessage &message)
{
    qDebug() << "=============================================" << message.service();

qDebug() << message.path();
qDebug() << message.interface() << DBUS_INTERFACE_DBUS;
qDebug() << message.member();

    // forward only NameOwnerChanged and ConsoleKit signals to PolkitTracker
    if ((message.type()        == QDBusMessage::SignalMessage
        && message.interface() == "org.freedesktop.DBus"
        && message.member()    == "NameOwnerChanged")
        || (!message.interface().isEmpty()
        && message.interface().startsWith(QLatin1String("org.freedesktop.ConsoleKit"))) ) {
        qDebug() << "inside";
        DBusMessage *msg = 0;
        DBusMessageIter args;
        msg = dbus_message_new_signal(
                message.path().toUtf8().data(), message.interface().toUtf8().data(),
                message.member().toUtf8().data());
        dbus_message_iter_init_append(msg, &args);
        foreach (QVariant arg, message.arguments()) {
            char *argument = qstrdup(arg.toString().toAscii());

            qDebug() << "First loop in" << argument;
            qDebug() << strlen(argument);

            switch (arg.type()) {
                case QVariant::String:
                    if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &argument)) {
                        qFatal("Out Of Memory!");
                        exit(1);
                    }
                    break;
                case QVariant::Bool:
                    if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, qstrdup(arg.toString().toAscii()))) {
                        qFatal("Out Of Memory!");
                        exit(1);
                    }
                    break;
                default:
                    qDebug() << "Crap!!";
                    break;
            }

        }
        qDebug() << "dbus_message_get_type() " <<  dbus_message_get_type (msg);
        qDebug() << "dbus_message_get_interface() " << dbus_message_get_interface (msg);
        qDebug() << "dbus_message_get_member() " << dbus_message_get_member (msg);
        qDebug() << "dbus_message_get_signature() " << dbus_message_get_signature (msg);
       qDebug() << "QT dbus_message_get_signature() " << message.signature();

       // WE NEED TO set the msg signature to "s" quite simple but
       // even QDbusMessage don't allow us to do that so...
       // i guess we need to get back and use
       // std DBus
        if (msg && polkit_tracker_dbus_func(d->pkTracker, msg)) {
        //THIS is getting emmited but there's a warning... and i hate
        // warnings :D
            qDebug() << "++++++++++++++++++++++ EMIT CONSOLE_KIT_DB_CHANGED";
            emit consoleKitDBChanged();
        }
    }
    qDebug() << "====================END======================" << message.service();
}

bool Context::hasError()
{
    if (d->m_hasError) {
        // try init again maybe something get
        // back to normal (as DBus might restarted, crashed...)
        d->init();
    }
    return d->m_hasError;
}

QString Context::lastError() const
{
    return d->m_lastError;
}

int Context::Private::io_add_watch(PolKitContext *context, int fd)
{
    qDebug() << "add_watch" << context << fd;

    QSocketNotifier *notify = new QSocketNotifier(fd, QSocketNotifier::Read, Context::instance());
    Context::instance()->d->m_watches[fd] = notify;
    notify->connect(notify, SIGNAL(activated(int)), Context::instance(), SLOT(watchActivatedContext(int)));

    return fd; // use simply the fd as the unique id for the watch
}

void Context::watchActivatedContext(int fd)
{
    Q_ASSERT(d->m_watches.contains(fd));

//    kDebug() << "watchActivated" << fd;

    polkit_context_io_func(d->pkContext, fd);
}

void Context::Private::io_remove_watch(PolKitContext *context, int id)
{
    Q_ASSERT(id > 0);
    qDebug() << "remove_watch" << context << id;
    if (!Context::instance()->d->m_watches.contains(id))
        return; // policykit likes to do this more than once

    QSocketNotifier *notify = Context::instance()->d->m_watches.take(id);
    notify->deleteLater();
    notify->setEnabled(false);
}

void Context::Private::pk_config_changed(PolKitContext *context, void *user_data)
{
    Q_UNUSED(context);
    Q_UNUSED(user_data);
    qDebug() << "PolicyKit reports that the config have changed";
    emit Context::instance()->configChanged();
}

QDomDocument Context::Private::introspect(const QString &service, const QString &path, const QDBusConnection &c)
{
    QDomDocument doc;

    QDBusInterface iface(service, path, "org.freedesktop.DBus.Introspectable", c);
    if (!iface.isValid()) {
        QDBusError err(iface.lastError());
        qDebug() << QString("Cannot introspect object %1 at %2:\n  %3 (%4)\n").arg(path).arg(
                      service).arg(err.name()).arg(err.message());
        return doc;
    }

    QDBusReply<QString> xml = iface.call("Introspect");

    if (!xml.isValid()) {
        QDBusError err(xml.error());
        if (err.isValid()) {
            qDebug() << QString("Call to object %1 at %2:\n  %3 (%4) failed\n").arg(
                        path).arg(service).arg(err.name()).arg(err.message());
        } else {
            qDebug() << QString("Invalid XML received from object %1 at %2\n").arg(
                    path).arg(service);
        }
        return doc;
    }

    doc.setContent(xml);
    return doc;
}

QStringList Context::Private::getSignals(const QDomDocument &doc)
{
    QStringList retlist;

    QDomElement node = doc.documentElement();
    QDomElement child = node.firstChildElement();

    while (!child.isNull()) {
        if (child.tagName() == QLatin1String("node") || child.tagName() == QLatin1String("interface")) {
            QDomElement iface = child.firstChildElement();
            while (!iface.isNull()) {
                if (iface.tagName() == QLatin1String("signal")) {
                    qDebug() << "Found signal: " << iface.attribute("name");
                    retlist.append(iface.attribute("name"));
                }
                iface = iface.nextSiblingElement();
            }
        }

        child = child.nextSiblingElement();
    }

    return retlist;
}

PolKitContext *Context::getPolKitContext()
{
    return d->pkContext;
}

PolKitTracker *Context::getPolKitTracker()
{
    return d->pkTracker;
}
<|endoftext|>