1 /************************************************************************* 2 * 3 * The Contents of this file are made available subject to the terms of 4 * the BSD license. 5 * 6 * Copyright 2000, 2010 Oracle and/or its affiliates. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of Sun Microsystems, Inc. nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 28 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 30 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 31 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 *************************************************************************/ 34 35 // __________ Imports __________ 36 37 import com.sun.star.uno.UnoRuntime; 38 39 import java.lang.*; 40 import java.util.*; 41 42 // __________ Implementation __________ 43 44 /** 45 * It's implement a static container which hold 46 * all opened documents and her views alive. 47 * It's possible to register/deregister such views, 48 * to get information about these and it provides 49 * some global functionality - like termination of 50 * this demo application. 51 * 52 * @author Andreas Schlüns 53 * @created 01.03.2002 08:42 54 */ 55 public class ViewContainer extends Thread 56 { 57 // ____________________ 58 59 /** 60 * provides a singleton view container 61 * Neccessary for terminate(9 functionality to be able 62 * to call Runtime.runFinilization(). 63 * 64 * @return a reference to the singleton ViewContainer instance 65 */ 66 public static synchronized ViewContainer getGlobalContainer() 67 { 68 if (maSingleton==null) 69 maSingleton=new ViewContainer(); 70 return maSingleton; 71 } 72 73 // ____________________ 74 75 /** 76 * ctor 77 * It's private - because nobody should create any instance 78 * expect the only global one, which wil be created by ourself! 79 */ 80 private ViewContainer() 81 { 82 mlViews = new Vector(); 83 mlListener = new Vector(); 84 mbShutdownActive = false ; 85 Runtime.getRuntime().addShutdownHook(this); 86 } 87 88 // ____________________ 89 90 /** 91 * This register a new view inside this global container 92 * (if it doesnt already exist). 93 * 94 * @param aView view which whish to be registered inside this container 95 */ 96 public void addView(Object aView) 97 { 98 synchronized(mlViews) 99 { 100 if(mlViews.contains(aView)==false) 101 mlViews.add(aView); 102 } 103 } 104 105 // ____________________ 106 107 /** 108 * This deregister a view from this global container. 109 * Normaly it should be the last reference to the view 110 * and her finalize() method should be called. 111 * If last view will be closed here - we terminate these 112 * java application too. Because there is no further 113 * visible frame anymore. 114 * 115 * @param aView 116 * view object which wish to be deregistered 117 */ 118 public void removeView(Object aView) 119 { 120 int nViewCount = 0; 121 synchronized(mlViews) 122 { 123 if(mlViews.contains(aView)==true) 124 mlViews.remove(aView); 125 126 nViewCount = mlViews.size(); 127 128 if (nViewCount<1) 129 mlViews = null; 130 } 131 // If this view is a registered shutdown listener on this view container 132 // too, we must call his interface and forget him as possible listener. 133 // It's neccessary to guarantee his dead ... 134 boolean bShutdownView = false; 135 synchronized(mlListener) 136 { 137 bShutdownView = mlListener.contains(aView); 138 if (bShutdownView==true) 139 mlListener.remove(aView); 140 } 141 if (bShutdownView==true) 142 ((IShutdownListener)aView).shutdown(); 143 144 // We use a system.exit() to finish the whole application. 145 // And further we have registered THIS instance as a possible shutdown 146 // hook at the runtime class. So our run() method will be called. 147 // Teh our view container should be empty - but 148 // our listener container can include some references. 149 // These objects wich to be informed then and release e.g. some 150 // remote references. 151 if (nViewCount<1) 152 { 153 boolean bNeccessary = false; 154 synchronized(this) 155 { 156 bNeccessary = ! mbShutdownActive; 157 } 158 if (bNeccessary==true) 159 { 160 System.out.println("call exit(0)!"); 161 System.exit(0); 162 } 163 } 164 } 165 166 // ____________________ 167 168 /** 169 * add/remove listener for possibe shutdown events 170 */ 171 public void addListener( IShutdownListener rListener ) 172 { 173 synchronized(mlListener) 174 { 175 if ( ! mlListener.contains(rListener) ) 176 mlListener.add(rListener); 177 } 178 } 179 180 // ____________________ 181 182 public void removeListener( IShutdownListener rListener ) 183 { 184 synchronized(mlListener) 185 { 186 if ( mlListener.contains(rListener) ) 187 mlListener.remove(rListener); 188 } 189 } 190 191 // ____________________ 192 193 /** 194 * Is called from current runtime system of the java machine 195 * on shutdown. We inform all current registered listener and 196 * views. They should deinitialize her internal things then. 197 */ 198 public void run() 199 { 200 synchronized(this) 201 { 202 if (mbShutdownActive) 203 return; 204 mbShutdownActive=true; 205 } 206 207 while( true ) 208 { 209 IShutdownListener aListener = null; 210 synchronized(mlListener) 211 { 212 try{ 213 aListener = (IShutdownListener)mlListener.firstElement(); 214 } catch(java.util.NoSuchElementException exEmpty) {} 215 } 216 if (aListener==null) 217 break; 218 219 aListener.shutdown(); 220 // May this listener has dergeistered himself. 221 // But if not we must do it for him. Our own 222 // method "removeListener()" ignore requests for 223 // already gone listener objects. 224 removeListener(aListener); 225 } 226 227 if (mlViews!=null) 228 { 229 synchronized(mlViews) 230 { 231 mlViews.clear(); 232 mlViews = null; 233 } 234 } 235 236 if (mlListener!=null) 237 { 238 synchronized(mlListener) 239 { 240 mlListener.clear(); 241 mlListener = null; 242 } 243 } 244 } 245 246 // ____________________ 247 248 /** 249 * @const BASICNAME it's used to create uinque names for all regieterd views 250 */ 251 private static final String BASICNAME = "Document View "; 252 253 // ____________________ 254 255 /** 256 * @member mbInplace indicates using of inplace office frames instead of outplace ones 257 * @member maSingleton singleton instance of this view container 258 * @member mlViews list of all currently registered document views 259 * @member mlListener list of all currently registered shutdown listener 260 * @member mbShutdownActive if this shutdown hook already was started it's not a good idea to 261 * call System.exit() again for other conditions. 262 * We supress it by using this variable! 263 */ 264 public static boolean mbInplace = false ; 265 private static ViewContainer maSingleton = null ; 266 private Vector mlViews ; 267 private Vector mlListener ; 268 private boolean mbShutdownActive ; 269 } 270