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