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 10cdf0e10cSrcweir * 11a5b190bfSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 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. 19cdf0e10cSrcweir * 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 } 49cdf0e10cSrcweir 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 } 63*5b780c4aSDamjan Jovanovic 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 { 112cdf0e10cSrcweir bDisposed= true; 113cdf0e10cSrcweir bInDispose= false; 114cdf0e10cSrcweir } 115cdf0e10cSrcweir } 116cf02f0b1SDamjan Jovanovic } 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