1a5b190bfSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3a5b190bfSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4a5b190bfSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5a5b190bfSAndrew Rist  * distributed with this work for additional information
6a5b190bfSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7a5b190bfSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8a5b190bfSAndrew Rist  * "License"); you may not use this file except in compliance
9a5b190bfSAndrew Rist  * with the License.  You may obtain a copy of the License at
10a5b190bfSAndrew Rist  *
11a5b190bfSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12a5b190bfSAndrew Rist  *
13a5b190bfSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14a5b190bfSAndrew Rist  * software distributed under the License is distributed on an
15a5b190bfSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16a5b190bfSAndrew Rist  * KIND, either express or implied.  See the License for the
17a5b190bfSAndrew Rist  * specific language governing permissions and limitations
18a5b190bfSAndrew Rist  * under the License.
19a5b190bfSAndrew Rist  *
20a5b190bfSAndrew Rist  *************************************************************/
21a5b190bfSAndrew Rist 
22a5b190bfSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir package com.sun.star.lib.uno.helper;
25*5b780c4aSDamjan Jovanovic import com.sun.star.lang.DisposedException;
26cdf0e10cSrcweir import com.sun.star.lang.XComponent;
27cdf0e10cSrcweir import com.sun.star.lang.XEventListener;
28cdf0e10cSrcweir import com.sun.star.lang.EventObject;
29cdf0e10cSrcweir import com.sun.star.uno.Type;
30cdf0e10cSrcweir 
31cdf0e10cSrcweir /** This class can be used as the base class for UNO components. In addition to the functionality ,which
32cdf0e10cSrcweir  *  is inherited from WeakBase, it implements com.sun.star.lang.XComponent.
33cdf0e10cSrcweir  */
34cdf0e10cSrcweir public class ComponentBase extends WeakBase implements XComponent
35cdf0e10cSrcweir {
36cdf0e10cSrcweir     private final boolean DEBUG= false;
37cdf0e10cSrcweir     protected MultiTypeInterfaceContainer listenerContainer;
38cdf0e10cSrcweir     protected boolean bInDispose= false;
39cdf0e10cSrcweir     protected boolean bDisposed= false;
40cdf0e10cSrcweir     static final Type  EVT_LISTENER_TYPE= new Type(XEventListener.class);
41cdf0e10cSrcweir 
42cdf0e10cSrcweir 
43cdf0e10cSrcweir     /** Creates a new instance of CompBase */
ComponentBase()44cdf0e10cSrcweir     public ComponentBase()
45cdf0e10cSrcweir     {
46cdf0e10cSrcweir         super();
47cdf0e10cSrcweir         listenerContainer= new MultiTypeInterfaceContainer();
48cdf0e10cSrcweir     }
49*5b780c4aSDamjan Jovanovic 
50*5b780c4aSDamjan Jovanovic     /** Checks whether this component (which you should have locked, prior to this call, and until you are done using) is disposed.
51*5b780c4aSDamjan Jovanovic       * @return whether this component is disposed
52*5b780c4aSDamjan Jovanovic       */
isDisposed()53*5b780c4aSDamjan Jovanovic     protected synchronized final boolean isDisposed() {
54*5b780c4aSDamjan Jovanovic         return bInDispose || bDisposed;
55*5b780c4aSDamjan Jovanovic     }
56*5b780c4aSDamjan Jovanovic 
57*5b780c4aSDamjan Jovanovic     /** Checks whether this component (which you should have locked, prior to this call, and until you are done using) is disposed, throwing DisposedException if it is. */
checkDisposed()58*5b780c4aSDamjan Jovanovic     protected synchronized final void checkDisposed() {
59*5b780c4aSDamjan Jovanovic         if (bInDispose || bDisposed) {
60*5b780c4aSDamjan Jovanovic             throw new DisposedException();
61*5b780c4aSDamjan Jovanovic         }
62*5b780c4aSDamjan Jovanovic     }
63cdf0e10cSrcweir 
64cdf0e10cSrcweir     /** Override to perform extra clean-up work. Provided for subclasses. It is
65cdf0e10cSrcweir         called during dispose()
66cdf0e10cSrcweir      */
preDisposing()67cdf0e10cSrcweir     protected void preDisposing()
68cdf0e10cSrcweir     {
69cdf0e10cSrcweir     }
70cdf0e10cSrcweir     /** Override to become notified right before the disposing action is performed.
71cdf0e10cSrcweir      */
postDisposing()72cdf0e10cSrcweir     protected void postDisposing()
73cdf0e10cSrcweir     {
74cdf0e10cSrcweir     }
75cdf0e10cSrcweir 
76cdf0e10cSrcweir 
77cdf0e10cSrcweir     /** Method of XComponent. It is called by the owning client when the component is not needed
78cdf0e10cSrcweir      *  anymore. The registered listeners are notified that this method has been called.
79cdf0e10cSrcweir      */
dispose()80cdf0e10cSrcweir     public void dispose()
81cdf0e10cSrcweir     {
82cdf0e10cSrcweir         // Determine in a thread-safe way if this is the first call to this method.
83cdf0e10cSrcweir         // Only then we proceed with the notification of event listeners.
84cdf0e10cSrcweir         // It is an error to call this method more then once.
85cdf0e10cSrcweir         boolean bDoDispose= false;
86cdf0e10cSrcweir         synchronized (this)
87cdf0e10cSrcweir         {
88cdf0e10cSrcweir             if ( ! bInDispose && ! bDisposed)
89cdf0e10cSrcweir             {
90cdf0e10cSrcweir                 bDoDispose= true;
91cdf0e10cSrcweir                 bInDispose= true;
92cdf0e10cSrcweir             }
93cdf0e10cSrcweir         }
9430acf5e8Spfg         // The notification occurs in an unsynchronized block in order to avoid
95cdf0e10cSrcweir         // deadlocks if one of the listeners calls back in a different thread on
96cdf0e10cSrcweir         // a synchronized method which uses the same object.
97cdf0e10cSrcweir         if (bDoDispose)
98cdf0e10cSrcweir         {
99cdf0e10cSrcweir             try
100cdf0e10cSrcweir             {
101cdf0e10cSrcweir                 preDisposing();
102cdf0e10cSrcweir                 listenerContainer.disposeAndClear(new EventObject(this));
103cdf0e10cSrcweir                 //notify subclasses that disposing is in progress
104cdf0e10cSrcweir                 postDisposing();
105cdf0e10cSrcweir             }
106cdf0e10cSrcweir             finally
107cdf0e10cSrcweir             {
108cdf0e10cSrcweir                 // finally makes sure that the  flags are set even if a RuntimeException is thrown.
109cdf0e10cSrcweir                 // That ensures that this function is only called once.
110cf02f0b1SDamjan Jovanovic                 synchronized (this)
111cf02f0b1SDamjan Jovanovic                 {
112cf02f0b1SDamjan Jovanovic                     bDisposed= true;
113cf02f0b1SDamjan Jovanovic                     bInDispose= false;
114cf02f0b1SDamjan Jovanovic                 }
115cdf0e10cSrcweir             }
116cdf0e10cSrcweir         }
117cdf0e10cSrcweir         else
118cdf0e10cSrcweir         {
119cdf0e10cSrcweir             // in a multithreaded environment, it can't be avoided, that dispose is called twice.
120cdf0e10cSrcweir             // However this condition is traced, because it MAY indicate an error.
121cdf0e10cSrcweir             if (DEBUG)
122cdf0e10cSrcweir                 System.out.println("OComponentHelper::dispose() - dispose called twice" );
123cdf0e10cSrcweir         }
124cdf0e10cSrcweir     }
125cdf0e10cSrcweir 
126cdf0e10cSrcweir     /** Method of XComponent.
127cdf0e10cSrcweir      */
removeEventListener(XEventListener xEventListener)128cdf0e10cSrcweir     public void removeEventListener(XEventListener xEventListener)
129cdf0e10cSrcweir     {
130cdf0e10cSrcweir         listenerContainer.removeInterface( EVT_LISTENER_TYPE, xEventListener);
131cdf0e10cSrcweir     }
132cdf0e10cSrcweir 
addEventListener(XEventListener listener)133cdf0e10cSrcweir     public void addEventListener(XEventListener listener)
134cdf0e10cSrcweir     {
135cdf0e10cSrcweir         boolean bDoDispose= false;
136cdf0e10cSrcweir         synchronized (this)
137cdf0e10cSrcweir         {
138cdf0e10cSrcweir             if (bDisposed || bInDispose)
139cdf0e10cSrcweir                 bDoDispose= true;
140cdf0e10cSrcweir             else
141cdf0e10cSrcweir                listenerContainer.addInterface(EVT_LISTENER_TYPE, listener);
142cdf0e10cSrcweir         }
143cdf0e10cSrcweir         if (bDoDispose )
144cdf0e10cSrcweir         {
145cdf0e10cSrcweir             listener.disposing( new EventObject(this));
146cdf0e10cSrcweir         }
147cdf0e10cSrcweir     }
148cdf0e10cSrcweir 
finalize()149cdf0e10cSrcweir     protected void finalize() throws Throwable
150cdf0e10cSrcweir     {
151cdf0e10cSrcweir         if ( ! bInDispose && ! bDisposed)
152cdf0e10cSrcweir             dispose();
153cdf0e10cSrcweir         super.finalize();
154cdf0e10cSrcweir     }
155cdf0e10cSrcweir }
156