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