diff options
Diffstat (limited to 'cli_ure/source/ure/uno')
-rw-r--r-- | cli_ure/source/ure/uno/util/DisposeGuard.cs | 59 | ||||
-rw-r--r-- | cli_ure/source/ure/uno/util/WeakAdapter.cs | 120 | ||||
-rw-r--r-- | cli_ure/source/ure/uno/util/WeakBase.cs | 178 | ||||
-rw-r--r-- | cli_ure/source/ure/uno/util/WeakComponentBase.cs | 194 |
4 files changed, 551 insertions, 0 deletions
diff --git a/cli_ure/source/ure/uno/util/DisposeGuard.cs b/cli_ure/source/ure/uno/util/DisposeGuard.cs new file mode 100644 index 000000000000..3c6c7671d64e --- /dev/null +++ b/cli_ure/source/ure/uno/util/DisposeGuard.cs @@ -0,0 +1,59 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +using System; +using unoidl.com.sun.star.lang; + +namespace uno.util +{ + +/** Helper class to conveniently auto dispose UNO objects from within + managed code. +*/ +public struct DisposeGuard : IDisposable +{ + private XComponent m_xComponent; + + /** ctor. + + @param obj target object + */ + public DisposeGuard( XComponent obj ) + { + m_xComponent = obj; + } + + /** System.IDisposable impl + */ + public void Dispose() + { + if (null != m_xComponent) + m_xComponent.dispose(); + } +} + +} diff --git a/cli_ure/source/ure/uno/util/WeakAdapter.cs b/cli_ure/source/ure/uno/util/WeakAdapter.cs new file mode 100644 index 000000000000..6f5b971131d3 --- /dev/null +++ b/cli_ure/source/ure/uno/util/WeakAdapter.cs @@ -0,0 +1,120 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +using System; +using unoidl.com.sun.star.uno; +using unoidl.com.sun.star.lang; + +namespace uno.util +{ + +/** An XAdapter implementation that holds a weak reference + (System.WeakReference) to an object. + Clients can register listeners (unoidl.com.sun.star.lang.XReference) + which are notified when the object (the one which is kept weak) is + being finalized. That is, that object is being destroyed because there + are not any hard references to it. +*/ +public class WeakAdapter : XAdapter +{ + // references the XWeak implementation + private WeakReference m_weakRef; + // contains XReference objects registered by addReference + private delegate void XReference_dispose(); + private XReference_dispose m_XReference_dispose; + + /** ctor. + + @param obj the object that is to be held weakly + */ + public WeakAdapter( Object obj ) + { + m_weakRef = new WeakReference( obj ); + m_XReference_dispose = null; + } + + /** Called by the XWeak implementation (WeakBase) when it is being + finalized. It is only being called once. + The registererd XReference listeners are notified. On notification + they are to unregister themselves. The notification is thread-safe. + However, it is possible to add a listener during the notification + process, which will never receive a notification. + To prevent this, one would have to synchronize this method with + the addReference method. But this can result in deadlocks in a + multithreaded environment. + */ + internal /* non-virtual */ void referentDying() + { + XReference_dispose call; + lock (this) + { + call = m_XReference_dispose; + m_XReference_dispose = null; + } + if (null != call) + call(); + } + + // XAdapter impl + + /** Called to obtain a hard reference o the object which is kept weakly + by this instance. + + @return hard reference to the object + */ + public Object queryAdapted() + { + return m_weakRef.Target; + } + /** Called by clients to register listener which are notified when the + weak object is dying. + + @param xReference a listener + */ + public void removeReference( XReference xReference ) + { + lock (this) + { + m_XReference_dispose -= + new XReference_dispose( xReference.dispose ); + } + } + /** Called by clients to unregister listeners. + + @param xReference a listener + */ + public void addReference( XReference xReference ) + { + lock (this) + { + m_XReference_dispose += + new XReference_dispose( xReference.dispose ); + } + } +} + +} diff --git a/cli_ure/source/ure/uno/util/WeakBase.cs b/cli_ure/source/ure/uno/util/WeakBase.cs new file mode 100644 index 000000000000..9e7d9023f198 --- /dev/null +++ b/cli_ure/source/ure/uno/util/WeakBase.cs @@ -0,0 +1,178 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +using System; +using System.Collections; +using unoidl.com.sun.star.uno; +using unoidl.com.sun.star.lang; + +namespace uno.util +{ + +/** This class can be used as a base class for UNO objects. + It implements the capability to be kept weakly + (unoidl.com.sun.star.uno.XWeak) and it implements + unoidl.com.sun.star.lang.XTypeProvider which is necessary for + using the object from StarBasic. +*/ +public class WeakBase : XWeak, XTypeProvider +{ + // Contains all WeakAdapter which have been created in this class + // They have to be notified when this object dies + private WeakAdapter m_adapter = null; + + protected static Hashtable s_types = new Hashtable(); + protected static Hashtable s_impl_ids = new Hashtable(); + + // XWeak impl + /** The returned XAdapter implementation can be used to keap a + weak reference to this object. + + @return a weak adapter + */ + public XAdapter queryAdapter() + { + if (null == m_adapter) + { + lock (this) + { + if (null == m_adapter) + m_adapter = new WeakAdapter( this ); + } + } + return m_adapter; + } + + /** Overrides of Object.Finalize method. + When there are no references to this object anymore, then the + garbage collector calls this method, thereby causing the adapter + object to be notified. The adapter, in turn, notifies all + listeners (unoidl.com.sun.star.uno.XReference). + */ + ~WeakBase() + { + if (null != m_adapter) + m_adapter.referentDying(); + } + + // XTypeProvider impl + + /** Returns an array of Type objects which represent all implemented + UNO interfaces of this object. + + @return Type objects of all implemented interfaces. + */ + public Type [] getTypes() + { + Type [] types; + Type type = GetType(); + lock (s_types) + { + types = (Type []) s_types[ type ]; + if (null == types) + { + Type [] interfaces = type.GetInterfaces(); + ArrayList list = new ArrayList( interfaces.Length ); + for ( Int32 pos = 0; pos < interfaces.Length; ++pos ) + { + Type iface = interfaces[ pos ]; + // xxx todo: as long as the bridge cannot introduce + // native CTS types into UNO on the fly + if (iface.FullName.StartsWith( "unoidl." )) + { + list.Add( iface ); + } + } + Int32 len = list.Count; + Type [] ar = new Type [ len ]; + for ( Int32 pos = 0; pos < len; ++pos ) + ar[ pos ] = (Type) list[ pos ]; + s_types[ type ] = ar; + types = ar; + } + } + return types; + } + + /** Provides an identifier that represents the set of UNO interfaces + implemented by this class. All instances of this class which run + in the same CLR return the same array. + + @return identifier as array of bytes + */ + public byte [] getImplementationId() + { + byte [] id; + Type type = GetType(); + lock (s_impl_ids) + { + id = (byte []) s_impl_ids[ type ]; + if (null == id) + { + Int32 hash = GetHashCode(); + String name = type.FullName; + Int32 len= name.Length; + + id = new byte[ 4 + (2 * len) ]; + id[ 0 ]= (byte) (hash & 0xff); + id[ 1 ]= (byte) ((hash >> 8) & 0xff); + id[ 2 ]= (byte) ((hash >> 16) & 0xff); + id[ 3 ]= (byte) ((hash >> 24) & 0xff); + + for ( Int32 pos = 0; pos < len; ++pos ) + { + UInt16 c = Convert.ToUInt16( name[ pos ] ); + id[ 4 + (2 * pos) ] = (byte) (c & 0xff); + id[ 4 + (2 * pos) +1 ] = (byte) ((c >> 8) & 0xff); + } + s_impl_ids[ type ] = id; + } + } + return id; + } + + // System.Object + public override String ToString() + { + System.Text.StringBuilder buf = + new System.Text.StringBuilder( base.ToString(), 256 ); + buf.Append( "\nUNO Object Implementation:\n\tImplementationId: " ); + buf.Append( getImplementationId() ); + buf.Append( "\n\tInterfaces: " ); + Type [] types = getTypes(); + for ( Int32 pos = 0; pos < types.Length; ++pos ) + { + buf.Append( types[ pos ].FullName ); + if (pos < (types.Length -1)) + buf.Append( ", " ); + } + return buf.ToString(); + } +} + +} + diff --git a/cli_ure/source/ure/uno/util/WeakComponentBase.cs b/cli_ure/source/ure/uno/util/WeakComponentBase.cs new file mode 100644 index 000000000000..1b688a5b2a80 --- /dev/null +++ b/cli_ure/source/ure/uno/util/WeakComponentBase.cs @@ -0,0 +1,194 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +using System; +using unoidl.com.sun.star.lang; + +namespace uno.util +{ + +/** This class can be used as a base class for UNO objects. + It implements the capability to be kept weakly + (unoidl.com.sun.star.uno.XWeak) and it implements + unoidl.com.sun.star.lang.XTypeProvider which is necessary for + using the object from StarBasic. + In addition, it implements the interface + unoidl.com.sun.star.lang.XComponent to be disposed explicitly. +*/ +public class WeakComponentBase : WeakBase, XComponent +{ + private delegate void t_disposing( EventObject evt ); + private t_disposing m_disposing = null; + private bool m_inDispose = false; + private bool m_disposed = false; + + /** Indicates whether object is alrady disposed. + + @return + true, if object has been disposed + */ + protected bool isDisposed() + { + lock (this) + { + return m_disposed; + } + } + + /** Checks whether this object is disposed and throws a DisposedException + if it is already disposed. + */ + protected void checkUnDisposed() + { + if (! isDisposed()) + { + throw new unoidl.com.sun.star.lang.DisposedException( + "object already disposed!", this ); + } + } + + ~WeakComponentBase() + { + bool doDispose; + lock (this) + { + doDispose = (!m_inDispose && !m_disposed); + } + if (doDispose) + { + dispose(); + } + } + + /** Override to perform extra clean-up work. Provided for subclasses. + It is called during dispose() + */ + protected void preDisposing() + { + } + + /** Override to become notified right before the disposing action is + performed. + */ + protected void postDisposing() + { + } + + // XComponent impl + /** This method is called by the owner of this object to explicitly + dispose it. This implementation of dispose() first notifies this object + via preDisposing(), then all registered event listeners and + finally this object again calling postDisposing(). + */ + public void dispose() + { + // Determine in a thread-safe way if this is the first call to this + // method. Only then we proceed with the notification of event + // listeners. It is an error to call this method more then once. + bool doDispose = false; + t_disposing call = null; + lock (this) + { + if (! m_inDispose && !m_disposed) + { + call = m_disposing; + m_disposing = null; + m_inDispose = true; + doDispose = true; + } + } + // The notification occures in an unsynchronized block in order to avoid + // deadlocks if one of the listeners calls back in a different thread on + // a synchronized method which uses the same object. + if (doDispose) + { + try + { + // call sub class + preDisposing(); + // send disposing notifications to listeners + if (null != call) + { + EventObject evt = new EventObject( this ); + call( evt ); + } + // call sub class + postDisposing(); + } + finally + { + // finally makes sure that the flags are set ensuring + // that this function is only called once. + m_disposed = true; + m_inDispose = false; + } + } + 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. +#if DEBUG + Console.WriteLine( + "WeakComponentBase.dispose() - dispose called twice" ); +#endif +// Debug.Fail( "WeakComponentBase.dispose() - dispose called twice" ); + } + } + /** Registers an event listener being notified when this object is disposed. + + @param xListener event listener + */ + public void addEventListener( XEventListener xListener ) + { + bool add; + lock (this) + { + add = (! m_inDispose && !m_disposed); + if (add) + m_disposing += new t_disposing( xListener.disposing ); + } + if (! add) + xListener.disposing( new EventObject( this ) ); + } + /** Revokes an event listener from being notified when this object + is disposed. + + @param xListener event listener + */ + public void removeEventListener( XEventListener xListener ) + { + lock (this) + { + if (! m_inDispose && !m_disposed) + m_disposing -= new t_disposing( xListener.disposing ); + } + } +} + +} |