/**************************************************************
 * 
 * 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 automatically 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 );
}

}

