/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2008 by Sun Microsystems, Inc.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: ComponentContext.java,v $
* $Revision: 1.8 $
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org 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 version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
package com.sun.star.comp.helper;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.Any;
import com.sun.star.uno.XComponentContext;
import com.sun.star.lang.XMultiComponentFactory;
import com.sun.star.lang.XSingleComponentFactory;
import com.sun.star.lang.XComponent;
import com.sun.star.lang.XEventListener;
import com.sun.star.lang.EventObject;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.Vector;
//==================================================================================================
class Disposer implements XEventListener
{
private XComponent m_xComp;
//----------------------------------------------------------------------------------------------
Disposer( XComponent xComp )
{
m_xComp = xComp;
}
//______________________________________________________________________________________________
public void disposing( EventObject Source )
{
m_xComp.dispose();
}
}
/** Component context implementation.
*/
public class ComponentContext implements XComponentContext, XComponent
{
private static final boolean DEBUG = false;
private static final String SMGR_NAME = "/singletons/com.sun.star.lang.theServiceManager";
private static final String TDMGR_NAME = "/singletons/com.sun.star.reflection.theTypeDescriptionManager";
private Hashtable m_table;
private XComponentContext m_xDelegate;
private XMultiComponentFactory m_xSMgr;
private boolean m_bDisposeSMgr;
private Vector m_eventListener;
/** Ctor to create a component context passing a hashtable for values and a delegator
reference. Entries of the passed hashtable are either direct values or
ComponentContextEntry objects.
@param table
entries
@param xDelegate
if values are not found, request is delegated to this object
*/
public ComponentContext( Hashtable table, XComponentContext xDelegate )
{
m_eventListener = new Vector();
m_table = table;
m_xDelegate = xDelegate;
m_xSMgr = null;
m_bDisposeSMgr = false;
Object o = table.get( SMGR_NAME );
if (o != null)
{
if (o instanceof ComponentContextEntry)
{
o = ((ComponentContextEntry)o).m_value;
}
m_xSMgr = UnoRuntime.queryInterface(
XMultiComponentFactory.class, o );
}
if (m_xSMgr != null)
{
m_bDisposeSMgr = true;
}
else if (m_xDelegate != null)
{
m_xSMgr = m_xDelegate.getServiceManager();
}
// listen for delegate
XComponent xComp = UnoRuntime.queryInterface(
XComponent.class, m_xDelegate );
if (xComp != null)
{
xComp.addEventListener( new Disposer( this ) );
}
}
// XComponentContext impl
//______________________________________________________________________________________________
public Object getValueByName( String rName )
{
Object o = m_table.get( rName );
if (o != null)
{
if (o instanceof ComponentContextEntry)
{
ComponentContextEntry entry = (ComponentContextEntry)o;
if (entry.m_lateInit != null)
{
Object xInstance = null;
try
{
String serviceName = (String)entry.m_lateInit;
if (serviceName != null)
{
if (m_xSMgr != null)
{
xInstance = m_xSMgr.createInstanceWithContext( serviceName, this );
}
else
{
if (DEBUG)
System.err.println( "### no service manager instance for late init of singleton instance \"" + rName + "\"!" );
}
}
else
{
XSingleComponentFactory xCompFac =
UnoRuntime.queryInterface(
XSingleComponentFactory.class, entry.m_lateInit );
if (xCompFac != null)
{
xInstance = xCompFac.createInstanceWithContext( this );
}
else
{
if (DEBUG)
System.err.println( "### neither service name nor service factory given for late init of singleton instance \"" + rName + "\"!" );
}
}
}
catch (com.sun.star.uno.Exception exc)
{
if (DEBUG)
System.err.println( "### exception occured on late init of singleton instance \"" + rName + "\": " + exc.getMessage() );
}
if (xInstance != null)
{
synchronized (entry)
{
if (entry.m_lateInit != null)
{
entry.m_value = xInstance;
entry.m_lateInit = null;
}
else // inited in the meantime
{
// dispose fresh service instance
XComponent xComp = UnoRuntime.queryInterface(
XComponent.class, xInstance );
if (xComp != null)
{
xComp.dispose();
}
}
}
}
else
{
if (DEBUG)
System.err.println( "### failed late init of singleton instance \"" + rName + "\"!" );
}
}
return entry.m_value;
}
else // direct value in map
{
return o;
}
}
else if (m_xDelegate != null)
{
return m_xDelegate.getValueByName( rName );
}
else
{
return Any.VOID;
}
}
//______________________________________________________________________________________________
public XMultiComponentFactory getServiceManager()
{
return m_xSMgr;
}
// XComponent impl
//______________________________________________________________________________________________
public void dispose()
{
if (DEBUG)
System.err.print( "> disposing context " + this );
// fire events
EventObject evt = new EventObject( this );
Enumeration eventListener = m_eventListener.elements();
while (eventListener.hasMoreElements())
{
XEventListener listener = (XEventListener)eventListener.nextElement();
listener.disposing( evt );
}
m_eventListener.removeAllElements();
XComponent tdmgr = null;
// dispose values, then service manager, then typdescription manager
Enumeration keys = m_table.keys();
while (keys.hasMoreElements())
{
String name = (String)keys.nextElement();
if (! name.equals( SMGR_NAME ))
{
Object o = m_table.get( name );
if (o instanceof ComponentContextEntry)
{
o = ((ComponentContextEntry)o).m_value;
}
XComponent xComp = UnoRuntime.queryInterface( XComponent.class, o );
if (xComp != null)
{
if (name.equals( TDMGR_NAME ))
{
tdmgr = xComp;
}
else
{
xComp.dispose();
}
}
}
}
m_table.clear();
// smgr
if (m_bDisposeSMgr)
{
XComponent xComp = UnoRuntime.queryInterface(
XComponent.class, m_xSMgr );
if (xComp != null)
{
xComp.dispose();
}
}
m_xSMgr = null;
// tdmgr
if (tdmgr != null)
{
tdmgr.dispose();
}
if (DEBUG)
System.err.println( "... finished" );
}
//______________________________________________________________________________________________
public void addEventListener( XEventListener xListener )
{
if (xListener == null)
throw new com.sun.star.uno.RuntimeException( "Listener must not be null" );
if (m_eventListener.contains( xListener ))
throw new com.sun.star.uno.RuntimeException( "Listener already registred." );
m_eventListener.addElement( xListener );
}
//______________________________________________________________________________________________
public void removeEventListener( XEventListener xListener )
{
if (xListener == null)
throw new com.sun.star.uno.RuntimeException( "Listener must not be null" );
if (! m_eventListener.contains( xListener ))
throw new com.sun.star.uno.RuntimeException( "Listener is not registered." );
m_eventListener.removeElement( xListener );
}
}