1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir using System;
29*cdf0e10cSrcweir using unoidl.com.sun.star.lang;
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir namespace uno.util
32*cdf0e10cSrcweir {
33*cdf0e10cSrcweir 
34*cdf0e10cSrcweir /** This class can be used as a base class for UNO objects.
35*cdf0e10cSrcweir     It implements the capability to be kept weakly
36*cdf0e10cSrcweir     (unoidl.com.sun.star.uno.XWeak) and it implements
37*cdf0e10cSrcweir     unoidl.com.sun.star.lang.XTypeProvider which is necessary for
38*cdf0e10cSrcweir     using the object from StarBasic.
39*cdf0e10cSrcweir     In addition, it implements the interface
40*cdf0e10cSrcweir     unoidl.com.sun.star.lang.XComponent to be disposed explicitly.
41*cdf0e10cSrcweir */
42*cdf0e10cSrcweir public class WeakComponentBase : WeakBase, XComponent
43*cdf0e10cSrcweir {
44*cdf0e10cSrcweir     private delegate void t_disposing( EventObject evt );
45*cdf0e10cSrcweir     private t_disposing m_disposing = null;
46*cdf0e10cSrcweir     private bool m_inDispose = false;
47*cdf0e10cSrcweir     private bool m_disposed = false;
48*cdf0e10cSrcweir 
49*cdf0e10cSrcweir     /** Indicates whether object is alrady disposed.
50*cdf0e10cSrcweir 
51*cdf0e10cSrcweir         @return
52*cdf0e10cSrcweir                 true, if object has been disposed
53*cdf0e10cSrcweir     */
54*cdf0e10cSrcweir     protected bool isDisposed()
55*cdf0e10cSrcweir     {
56*cdf0e10cSrcweir         lock (this)
57*cdf0e10cSrcweir         {
58*cdf0e10cSrcweir             return m_disposed;
59*cdf0e10cSrcweir         }
60*cdf0e10cSrcweir     }
61*cdf0e10cSrcweir 
62*cdf0e10cSrcweir     /** Checks whether this object is disposed and throws a DisposedException
63*cdf0e10cSrcweir         if it is already disposed.
64*cdf0e10cSrcweir     */
65*cdf0e10cSrcweir     protected void checkUnDisposed()
66*cdf0e10cSrcweir     {
67*cdf0e10cSrcweir         if (! isDisposed())
68*cdf0e10cSrcweir         {
69*cdf0e10cSrcweir             throw new unoidl.com.sun.star.lang.DisposedException(
70*cdf0e10cSrcweir                 "object already disposed!", this );
71*cdf0e10cSrcweir         }
72*cdf0e10cSrcweir     }
73*cdf0e10cSrcweir 
74*cdf0e10cSrcweir     ~WeakComponentBase()
75*cdf0e10cSrcweir     {
76*cdf0e10cSrcweir         bool doDispose;
77*cdf0e10cSrcweir         lock (this)
78*cdf0e10cSrcweir         {
79*cdf0e10cSrcweir             doDispose = (!m_inDispose && !m_disposed);
80*cdf0e10cSrcweir         }
81*cdf0e10cSrcweir         if (doDispose)
82*cdf0e10cSrcweir         {
83*cdf0e10cSrcweir             dispose();
84*cdf0e10cSrcweir         }
85*cdf0e10cSrcweir     }
86*cdf0e10cSrcweir 
87*cdf0e10cSrcweir     /** Override to perform extra clean-up work. Provided for subclasses.
88*cdf0e10cSrcweir         It is called during dispose()
89*cdf0e10cSrcweir     */
90*cdf0e10cSrcweir     protected void preDisposing()
91*cdf0e10cSrcweir     {
92*cdf0e10cSrcweir     }
93*cdf0e10cSrcweir 
94*cdf0e10cSrcweir     /** Override to become notified right before the disposing action is
95*cdf0e10cSrcweir         performed.
96*cdf0e10cSrcweir     */
97*cdf0e10cSrcweir     protected void postDisposing()
98*cdf0e10cSrcweir     {
99*cdf0e10cSrcweir     }
100*cdf0e10cSrcweir 
101*cdf0e10cSrcweir     // XComponent impl
102*cdf0e10cSrcweir     /** This method is called by the owner of this object to explicitly
103*cdf0e10cSrcweir         dispose it.  This implementation of dispose() first notifies this object
104*cdf0e10cSrcweir         via preDisposing(), then  all registered event listeners and
105*cdf0e10cSrcweir         finally this object again calling postDisposing().
106*cdf0e10cSrcweir     */
107*cdf0e10cSrcweir     public void dispose()
108*cdf0e10cSrcweir     {
109*cdf0e10cSrcweir         // Determine in a thread-safe way if this is the first call to this
110*cdf0e10cSrcweir         // method.  Only then we proceed with the notification of event
111*cdf0e10cSrcweir         // listeners.  It is an error to call this method more then once.
112*cdf0e10cSrcweir         bool doDispose = false;
113*cdf0e10cSrcweir         t_disposing call = null;
114*cdf0e10cSrcweir         lock (this)
115*cdf0e10cSrcweir         {
116*cdf0e10cSrcweir             if (! m_inDispose && !m_disposed)
117*cdf0e10cSrcweir             {
118*cdf0e10cSrcweir                 call = m_disposing;
119*cdf0e10cSrcweir                 m_disposing = null;
120*cdf0e10cSrcweir                 m_inDispose = true;
121*cdf0e10cSrcweir                 doDispose = true;
122*cdf0e10cSrcweir             }
123*cdf0e10cSrcweir         }
124*cdf0e10cSrcweir         // The notification occures in an unsynchronized block in order to avoid
125*cdf0e10cSrcweir         // deadlocks if one of the listeners calls back in a different thread on
126*cdf0e10cSrcweir         // a synchronized method which uses the same object.
127*cdf0e10cSrcweir         if (doDispose)
128*cdf0e10cSrcweir         {
129*cdf0e10cSrcweir             try
130*cdf0e10cSrcweir             {
131*cdf0e10cSrcweir                 // call sub class
132*cdf0e10cSrcweir                 preDisposing();
133*cdf0e10cSrcweir                 // send disposing notifications to listeners
134*cdf0e10cSrcweir                 if (null != call)
135*cdf0e10cSrcweir                 {
136*cdf0e10cSrcweir                     EventObject evt = new EventObject( this );
137*cdf0e10cSrcweir                     call( evt );
138*cdf0e10cSrcweir                 }
139*cdf0e10cSrcweir                 // call sub class
140*cdf0e10cSrcweir                 postDisposing();
141*cdf0e10cSrcweir             }
142*cdf0e10cSrcweir             finally
143*cdf0e10cSrcweir             {
144*cdf0e10cSrcweir                 // finally makes sure that the flags are set ensuring
145*cdf0e10cSrcweir                 // that this function is only called once.
146*cdf0e10cSrcweir                 m_disposed = true;
147*cdf0e10cSrcweir                 m_inDispose = false;
148*cdf0e10cSrcweir             }
149*cdf0e10cSrcweir         }
150*cdf0e10cSrcweir         else
151*cdf0e10cSrcweir         {
152*cdf0e10cSrcweir             // in a multithreaded environment, it can't be avoided,
153*cdf0e10cSrcweir             // that dispose is called twice.
154*cdf0e10cSrcweir             // However this condition is traced, because it MAY indicate an
155*cdf0e10cSrcweir             // error.
156*cdf0e10cSrcweir #if DEBUG
157*cdf0e10cSrcweir             Console.WriteLine(
158*cdf0e10cSrcweir                 "WeakComponentBase.dispose() - dispose called twice" );
159*cdf0e10cSrcweir #endif
160*cdf0e10cSrcweir //             Debug.Fail( "WeakComponentBase.dispose() - dispose called twice" );
161*cdf0e10cSrcweir         }
162*cdf0e10cSrcweir     }
163*cdf0e10cSrcweir     /** Registers an event listener being notified when this object is disposed.
164*cdf0e10cSrcweir 
165*cdf0e10cSrcweir         @param xListener event listener
166*cdf0e10cSrcweir     */
167*cdf0e10cSrcweir     public void addEventListener( XEventListener xListener )
168*cdf0e10cSrcweir     {
169*cdf0e10cSrcweir         bool add;
170*cdf0e10cSrcweir         lock (this)
171*cdf0e10cSrcweir         {
172*cdf0e10cSrcweir             add = (! m_inDispose && !m_disposed);
173*cdf0e10cSrcweir             if (add)
174*cdf0e10cSrcweir                 m_disposing += new t_disposing( xListener.disposing );
175*cdf0e10cSrcweir         }
176*cdf0e10cSrcweir         if (! add)
177*cdf0e10cSrcweir             xListener.disposing( new EventObject( this ) );
178*cdf0e10cSrcweir     }
179*cdf0e10cSrcweir     /** Revokes an event listener from being notified when this object
180*cdf0e10cSrcweir         is disposed.
181*cdf0e10cSrcweir 
182*cdf0e10cSrcweir         @param xListener event listener
183*cdf0e10cSrcweir     */
184*cdf0e10cSrcweir     public void removeEventListener( XEventListener xListener )
185*cdf0e10cSrcweir     {
186*cdf0e10cSrcweir         lock (this)
187*cdf0e10cSrcweir         {
188*cdf0e10cSrcweir             if (! m_inDispose && !m_disposed)
189*cdf0e10cSrcweir                 m_disposing -= new t_disposing( xListener.disposing );
190*cdf0e10cSrcweir         }
191*cdf0e10cSrcweir     }
192*cdf0e10cSrcweir }
193*cdf0e10cSrcweir 
194*cdf0e10cSrcweir }
195