/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_cppuhelper.hxx"
#include <rtl/string.hxx>
#include <osl/diagnose.h>
#include <cppuhelper/component.hxx>
#include <cppuhelper/queryinterface.hxx>
#include <cppuhelper/typeprovider.hxx>
#include "com/sun/star/uno/RuntimeException.hpp"

using namespace osl;
using namespace rtl;
using namespace com::sun::star;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;

namespace cppu
{

//	----------------------------------------------------
//	class OComponentHelper
//	----------------------------------------------------

OComponentHelper::OComponentHelper( Mutex & rMutex ) SAL_THROW( () )
	: rBHelper( rMutex )
{
}
OComponentHelper::~OComponentHelper() SAL_THROW( (RuntimeException) )
{
}

Any OComponentHelper::queryInterface( Type const & rType ) throw (RuntimeException)
{
    return OWeakAggObject::queryInterface( rType );
}
Any OComponentHelper::queryAggregation( Type const & rType ) throw (RuntimeException)
{
    if (rType == ::getCppuType( (Reference< lang::XComponent > const *)0 ))
    {
        void * p = static_cast< lang::XComponent * >( this );
        return Any( &p, rType );
    }
    else if (rType == ::getCppuType( (Reference< lang::XTypeProvider > const *)0 ))
    {
        void * p = static_cast< lang::XTypeProvider * >( this );
        return Any( &p, rType );
    }
    return OWeakAggObject::queryAggregation( rType );
}
void OComponentHelper::acquire() throw ()
{
	OWeakAggObject::acquire();
}

void OComponentHelper::release() throw()
{
	Reference<XInterface > x( xDelegator );
	if (! x.is())
	{
		if (osl_decrementInterlockedCount( &m_refCount ) == 0)
		{
			if (! rBHelper.bDisposed)
			{
                // *before* again incrementing our ref count, ensure that our weak connection point
                // will not create references to us anymore (via XAdapter::queryAdapted)
                disposeWeakConnectionPoint();

				Reference<XInterface > xHoldAlive( *this );
				// First dispose
				try
				{
					dispose();
				}
				catch (::com::sun::star::uno::RuntimeException & exc)
				{
					// release should not throw exceptions
#if OSL_DEBUG_LEVEL > 0
                    OString msg( OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) );
                    OSL_ENSURE( 0, msg.getStr() );
#else
                    (void) exc; // avoid warning about unused variable
#endif
				}

				// only the alive ref holds the object
				OSL_ASSERT( m_refCount == 1 );
				// destroy the object if xHoldAlive decrement the refcount to 0
				return;
			}
		}
		// restore the reference count
		osl_incrementInterlockedCount( &m_refCount );
	}
	OWeakAggObject::release();
}

Sequence< Type > OComponentHelper::getTypes() throw (RuntimeException)
{
	static OTypeCollection * s_pTypes = 0;
	if (! s_pTypes)
	{
		MutexGuard aGuard( Mutex::getGlobalMutex() );
		if (! s_pTypes)
		{
			static OTypeCollection s_aTypes(
				::getCppuType( (const Reference< lang::XComponent > *)0 ),
				::getCppuType( (const Reference< lang::XTypeProvider > *)0 ),
				::getCppuType( (const Reference< XAggregation > *)0 ),
				::getCppuType( (const Reference< XWeak > *)0 ) );
			s_pTypes = &s_aTypes;
		}
	}
	return s_pTypes->getTypes();
}

// XComponent
void OComponentHelper::disposing()
{
}

// XComponent
void OComponentHelper::dispose()
	throw(::com::sun::star::uno::RuntimeException)
{
	// An frequently programming error is to release the last
	// reference to this object in the disposing message.
	// Make it rubust, hold a self Reference.
	Reference<XComponent > xSelf( this );

	// Guard dispose against multible threading
	// Remark: It is an error to call dispose more than once
	sal_Bool bDoDispose = sal_False;
	{
	MutexGuard aGuard( rBHelper.rMutex );
	if( !rBHelper.bDisposed && !rBHelper.bInDispose )
	{
		// only one call go into this section
		rBHelper.bInDispose = sal_True;
		bDoDispose = sal_True;
	}
	}

	// Do not hold the mutex because we are broadcasting
	if( bDoDispose )
	{
		// Create an event with this as sender
		try
		{
            try
            {
                Reference<XInterface > xSource(
                    Reference<XInterface >::query( (XComponent *)this ) );
                EventObject aEvt;
                aEvt.Source = xSource;
                // inform all listeners to release this object
                // The listener container are automaticly cleared
                rBHelper.aLC.disposeAndClear( aEvt );
                // notify subclasses to do their dispose
                disposing();
            }
            catch (...)
            {
                MutexGuard aGuard( rBHelper.rMutex );
                // bDispose and bInDisposing must be set in this order:
                rBHelper.bDisposed = sal_True;
                rBHelper.bInDispose = sal_False;
                throw;
            }
            MutexGuard aGuard( rBHelper.rMutex );
            // bDispose and bInDisposing must be set in this order:
            rBHelper.bDisposed = sal_True;
            rBHelper.bInDispose = sal_False;
		}
		catch (RuntimeException &)
		{
			throw;
		}
		catch (Exception & exc)
		{
            throw RuntimeException(
                OUString( RTL_CONSTASCII_USTRINGPARAM(
                              "unexpected UNO exception caught: ") ) +
                exc.Message, Reference< XInterface >() );
		}
	}
	else
	{
		// in a multithreaded environment, it can't be avoided,
		// that dispose is called twice.
		// However this condition is traced, because it MAY indicate an error.
		OSL_TRACE( "OComponentHelper::dispose() - dispose called twice" );
	}
}

// XComponent
void OComponentHelper::addEventListener(
	const Reference<XEventListener > & rxListener )
	throw(::com::sun::star::uno::RuntimeException)
{
	ClearableMutexGuard aGuard( rBHelper.rMutex );
	if (rBHelper.bDisposed || rBHelper.bInDispose)
	{
        aGuard.clear();
        Reference< XInterface > x( (XComponent *)this, UNO_QUERY );
		rxListener->disposing( EventObject( x ) );
	}
	else
	{
		rBHelper.addListener( ::getCppuType( &rxListener ) , rxListener );
	}
}

// XComponent
void OComponentHelper::removeEventListener(
	const Reference<XEventListener > & rxListener )
	throw(::com::sun::star::uno::RuntimeException)
{
	rBHelper.removeListener( ::getCppuType( &rxListener ) , rxListener );
}

}

