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.DisposedException; 26 import com.sun.star.lang.XComponent; 27 import com.sun.star.lang.XEventListener; 28 import com.sun.star.lang.EventObject; 29 import com.sun.star.uno.Type; 30 31 /** This class can be used as the base class for UNO components. In addition to the functionality ,which 32 * is inherited from WeakBase, it implements com.sun.star.lang.XComponent. 33 */ 34 public class ComponentBase extends WeakBase implements XComponent 35 { 36 private final boolean DEBUG= false; 37 protected MultiTypeInterfaceContainer listenerContainer; 38 protected boolean bInDispose= false; 39 protected boolean bDisposed= false; 40 static final Type EVT_LISTENER_TYPE= new Type(XEventListener.class); 41 42 43 /** Creates a new instance of CompBase */ ComponentBase()44 public ComponentBase() 45 { 46 super(); 47 listenerContainer= new MultiTypeInterfaceContainer(); 48 } 49 50 /** Checks whether this component (which you should have locked, prior to this call, and until you are done using) is disposed. 51 * @return whether this component is disposed 52 */ isDisposed()53 protected synchronized final boolean isDisposed() { 54 return bInDispose || bDisposed; 55 } 56 57 /** 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 protected synchronized final void checkDisposed() { 59 if (bInDispose || bDisposed) { 60 throw new DisposedException(); 61 } 62 } 63 64 /** Override to perform extra clean-up work. Provided for subclasses. It is 65 called during dispose() 66 */ preDisposing()67 protected void preDisposing() 68 { 69 } 70 /** Override to become notified right before the disposing action is performed. 71 */ postDisposing()72 protected void postDisposing() 73 { 74 } 75 76 77 /** Method of XComponent. It is called by the owning client when the component is not needed 78 * anymore. The registered listeners are notified that this method has been called. 79 */ dispose()80 public void dispose() 81 { 82 // Determine in a thread-safe way if this is the first call to this method. 83 // Only then we proceed with the notification of event listeners. 84 // It is an error to call this method more then once. 85 boolean bDoDispose= false; 86 synchronized (this) 87 { 88 if ( ! bInDispose && ! bDisposed) 89 { 90 bDoDispose= true; 91 bInDispose= true; 92 } 93 } 94 // The notification occurs in an unsynchronized block in order to avoid 95 // deadlocks if one of the listeners calls back in a different thread on 96 // a synchronized method which uses the same object. 97 if (bDoDispose) 98 { 99 try 100 { 101 preDisposing(); 102 listenerContainer.disposeAndClear(new EventObject(this)); 103 //notify subclasses that disposing is in progress 104 postDisposing(); 105 } 106 finally 107 { 108 // finally makes sure that the flags are set even if a RuntimeException is thrown. 109 // That ensures that this function is only called once. 110 synchronized (this) 111 { 112 bDisposed= true; 113 bInDispose= false; 114 } 115 } 116 } 117 else 118 { 119 // in a multithreaded environment, it can't be avoided, that dispose is called twice. 120 // However this condition is traced, because it MAY indicate an error. 121 if (DEBUG) 122 System.out.println("OComponentHelper::dispose() - dispose called twice" ); 123 } 124 } 125 126 /** Method of XComponent. 127 */ removeEventListener(XEventListener xEventListener)128 public void removeEventListener(XEventListener xEventListener) 129 { 130 listenerContainer.removeInterface( EVT_LISTENER_TYPE, xEventListener); 131 } 132 addEventListener(XEventListener listener)133 public void addEventListener(XEventListener listener) 134 { 135 boolean bDoDispose= false; 136 synchronized (this) 137 { 138 if (bDisposed || bInDispose) 139 bDoDispose= true; 140 else 141 listenerContainer.addInterface(EVT_LISTENER_TYPE, listener); 142 } 143 if (bDoDispose ) 144 { 145 listener.disposing( new EventObject(this)); 146 } 147 } 148 finalize()149 protected void finalize() throws Throwable 150 { 151 if ( ! bInDispose && ! bDisposed) 152 dispose(); 153 super.finalize(); 154 } 155 } 156