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