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 */ 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 */ 52 protected void preDisposing() 53 { 54 } 55 /** Override to become notified right before the disposing action is performed. 56 */ 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 */ 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 occurs 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 synchronized (this) 96 { 97 bDisposed= true; 98 bInDispose= false; 99 } 100 } 101 } 102 else 103 { 104 // in a multithreaded environment, it can't be avoided, that dispose is called twice. 105 // However this condition is traced, because it MAY indicate an error. 106 if (DEBUG) 107 System.out.println("OComponentHelper::dispose() - dispose called twice" ); 108 } 109 } 110 111 /** Method of XComponent. 112 */ 113 public void removeEventListener(XEventListener xEventListener) 114 { 115 listenerContainer.removeInterface( EVT_LISTENER_TYPE, xEventListener); 116 } 117 118 public void addEventListener(XEventListener listener) 119 { 120 boolean bDoDispose= false; 121 synchronized (this) 122 { 123 if (bDisposed || bInDispose) 124 bDoDispose= true; 125 else 126 listenerContainer.addInterface(EVT_LISTENER_TYPE, listener); 127 } 128 if (bDoDispose ) 129 { 130 listener.disposing( new EventObject(this)); 131 } 132 } 133 134 protected void finalize() throws Throwable 135 { 136 if ( ! bInDispose && ! bDisposed) 137 dispose(); 138 super.finalize(); 139 } 140 } 141