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 // __________ Imports __________ 25 26 import com.sun.star.uno.UnoRuntime; 27 28 import java.lang.*; 29 import java.util.*; 30 31 // __________ Implementation __________ 32 33 /** 34 * It's implement a static container which hold 35 * all opened documents and her views alive. 36 * It's possible to register/deregister such views, 37 * to get information about these and it provides 38 * some global functionality - like termination of 39 * this demo application. 40 * 41 * @author Andreas Schlüns 42 * @created 01.03.2002 08:42 43 */ 44 public class ViewContainer extends Thread 45 { 46 // ____________________ 47 48 /** 49 * provides a singleton view container 50 * Necessary for terminate(9 functionality to be able 51 * to call Runtime.runFinilization(). 52 * 53 * @return a reference to the singleton ViewContainer instance 54 */ getGlobalContainer()55 public static synchronized ViewContainer getGlobalContainer() 56 { 57 if (maSingleton==null) 58 maSingleton=new ViewContainer(); 59 return maSingleton; 60 } 61 62 // ____________________ 63 64 /** 65 * ctor 66 * It's private - because nobody should create any instance 67 * expect the only global one, which wil be created by ourself! 68 */ ViewContainer()69 private ViewContainer() 70 { 71 mlViews = new Vector(); 72 mlListener = new Vector(); 73 mbShutdownActive = false ; 74 Runtime.getRuntime().addShutdownHook(this); 75 } 76 77 // ____________________ 78 79 /** 80 * This register a new view inside this global container 81 * (if it doesn't already exist). 82 * 83 * @param aView view which whish to be registered inside this container 84 */ addView(Object aView)85 public void addView(Object aView) 86 { 87 synchronized(mlViews) 88 { 89 if(mlViews.contains(aView)==false) 90 mlViews.add(aView); 91 } 92 } 93 94 // ____________________ 95 96 /** 97 * This deregister a view from this global container. 98 * Normally it should be the last reference to the view 99 * and her finalize() method should be called. 100 * If last view will be closed here - we terminate these 101 * java application too. Because there is no further 102 * visible frame anymore. 103 * 104 * @param aView 105 * view object which wish to be deregistered 106 */ removeView(Object aView)107 public void removeView(Object aView) 108 { 109 int nViewCount = 0; 110 synchronized(mlViews) 111 { 112 if(mlViews.contains(aView)==true) 113 mlViews.remove(aView); 114 115 nViewCount = mlViews.size(); 116 117 if (nViewCount<1) 118 mlViews = null; 119 } 120 // If this view is a registered shutdown listener on this view container 121 // too, we must call his interface and forget him as possible listener. 122 // It's necessary to guarantee his dead ... 123 boolean bShutdownView = false; 124 synchronized(mlListener) 125 { 126 bShutdownView = mlListener.contains(aView); 127 if (bShutdownView==true) 128 mlListener.remove(aView); 129 } 130 if (bShutdownView==true) 131 ((IShutdownListener)aView).shutdown(); 132 133 // We use a system.exit() to finish the whole application. 134 // And further we have registered THIS instance as a possible shutdown 135 // hook at the runtime class. So our run() method will be called. 136 // Teh our view container should be empty - but 137 // our listener container can include some references. 138 // These objects which to be informed then and release e.g. some 139 // remote references. 140 if (nViewCount<1) 141 { 142 boolean bNeccessary = false; 143 synchronized(this) 144 { 145 bNeccessary = ! mbShutdownActive; 146 } 147 if (bNeccessary==true) 148 { 149 System.out.println("call exit(0)!"); 150 System.exit(0); 151 } 152 } 153 } 154 155 // ____________________ 156 157 /** 158 * add/remove listener for possibe shutdown events 159 */ addListener( IShutdownListener rListener )160 public void addListener( IShutdownListener rListener ) 161 { 162 synchronized(mlListener) 163 { 164 if ( ! mlListener.contains(rListener) ) 165 mlListener.add(rListener); 166 } 167 } 168 169 // ____________________ 170 removeListener( IShutdownListener rListener )171 public void removeListener( IShutdownListener rListener ) 172 { 173 synchronized(mlListener) 174 { 175 if ( mlListener.contains(rListener) ) 176 mlListener.remove(rListener); 177 } 178 } 179 180 // ____________________ 181 182 /** 183 * Is called from current runtime system of the java machine 184 * on shutdown. We inform all current registered listener and 185 * views. They should deinitialize her internal things then. 186 */ run()187 public void run() 188 { 189 synchronized(this) 190 { 191 if (mbShutdownActive) 192 return; 193 mbShutdownActive=true; 194 } 195 196 while( true ) 197 { 198 IShutdownListener aListener = null; 199 synchronized(mlListener) 200 { 201 try{ 202 aListener = (IShutdownListener)mlListener.firstElement(); 203 } catch(java.util.NoSuchElementException exEmpty) {} 204 } 205 if (aListener==null) 206 break; 207 208 aListener.shutdown(); 209 // May this listener has dergeistered himself. 210 // But if not we must do it for him. Our own 211 // method "removeListener()" ignore requests for 212 // already gone listener objects. 213 removeListener(aListener); 214 } 215 216 if (mlViews!=null) 217 { 218 synchronized(mlViews) 219 { 220 mlViews.clear(); 221 mlViews = null; 222 } 223 } 224 225 if (mlListener!=null) 226 { 227 synchronized(mlListener) 228 { 229 mlListener.clear(); 230 mlListener = null; 231 } 232 } 233 } 234 235 // ____________________ 236 237 /** 238 * @const BASICNAME it's used to create uinque names for all regieterd views 239 */ 240 private static final String BASICNAME = "Document View "; 241 242 // ____________________ 243 244 /** 245 * @member mbInplace indicates using of inplace office frames instead of outplace ones 246 * @member maSingleton singleton instance of this view container 247 * @member mlViews list of all currently registered document views 248 * @member mlListener list of all currently registered shutdown listener 249 * @member mbShutdownActive if this shutdown hook already was started it's not a good idea to 250 * call System.exit() again for other conditions. 251 * We suppress it by using this variable! 252 */ 253 public static boolean mbInplace = false ; 254 private static ViewContainer maSingleton = null ; 255 private Vector mlViews ; 256 private Vector mlListener ; 257 private boolean mbShutdownActive ; 258 } 259