1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 package com.sun.star.comp.helper;
28 
29 import com.sun.star.uno.UnoRuntime;
30 import com.sun.star.uno.Any;
31 
32 import com.sun.star.uno.XComponentContext;
33 import com.sun.star.lang.XMultiComponentFactory;
34 import com.sun.star.lang.XSingleComponentFactory;
35 import com.sun.star.lang.XComponent;
36 import com.sun.star.lang.XEventListener;
37 import com.sun.star.lang.EventObject;
38 
39 import java.util.Hashtable;
40 import java.util.Enumeration;
41 import java.util.Vector;
42 
43 
44 //==================================================================================================
45 class Disposer implements XEventListener
46 {
47     private XComponent m_xComp;
48 
49     //----------------------------------------------------------------------------------------------
50     Disposer( XComponent xComp )
51     {
52         m_xComp = xComp;
53     }
54     //______________________________________________________________________________________________
55     public void disposing( EventObject Source )
56     {
57         m_xComp.dispose();
58     }
59 }
60 
61 /** Component context implementation.
62 */
63 public class ComponentContext implements XComponentContext, XComponent
64 {
65     private static final boolean DEBUG = false;
66     private static final String SMGR_NAME = "/singletons/com.sun.star.lang.theServiceManager";
67     private static final String TDMGR_NAME = "/singletons/com.sun.star.reflection.theTypeDescriptionManager";
68 
69     private Hashtable m_table;
70     private XComponentContext m_xDelegate;
71 
72     private XMultiComponentFactory m_xSMgr;
73     private boolean m_bDisposeSMgr;
74 
75     private Vector m_eventListener;
76 
77     /** Ctor to create a component context passing a hashtable for values and a delegator
78         reference. Entries of the passed hashtable are either direct values or
79         ComponentContextEntry objects.
80 
81         @param table
82                entries
83         @param xDelegate
84                if values are not found, request is delegated to this object
85     */
86     public ComponentContext( Hashtable table, XComponentContext xDelegate )
87     {
88         m_eventListener = new Vector();
89         m_table = table;
90         m_xDelegate = xDelegate;
91         m_xSMgr = null;
92         m_bDisposeSMgr = false;
93 
94         Object o = table.get( SMGR_NAME );
95         if (o != null)
96         {
97             if (o instanceof ComponentContextEntry)
98             {
99                 o = ((ComponentContextEntry)o).m_value;
100             }
101             m_xSMgr = UnoRuntime.queryInterface(
102                 XMultiComponentFactory.class, o );
103         }
104         if (m_xSMgr != null)
105         {
106             m_bDisposeSMgr = true;
107         }
108         else if (m_xDelegate != null)
109         {
110             m_xSMgr = m_xDelegate.getServiceManager();
111         }
112 
113         // listen for delegate
114         XComponent xComp = UnoRuntime.queryInterface(
115             XComponent.class, m_xDelegate );
116         if (xComp != null)
117         {
118             xComp.addEventListener( new Disposer( this ) );
119         }
120     }
121 
122     // XComponentContext impl
123     //______________________________________________________________________________________________
124     public Object getValueByName( String rName )
125     {
126         Object o = m_table.get( rName );
127         if (o != null)
128         {
129             if (o instanceof ComponentContextEntry)
130             {
131                 ComponentContextEntry entry = (ComponentContextEntry)o;
132                 if (entry.m_lateInit != null)
133                 {
134                     Object xInstance = null;
135 
136                     try
137                     {
138                         String serviceName = (String)entry.m_lateInit;
139                         if (serviceName != null)
140                         {
141                             if (m_xSMgr != null)
142                             {
143                                 xInstance = m_xSMgr.createInstanceWithContext( serviceName, this );
144                             }
145                             else
146                             {
147                                 if (DEBUG)
148                                     System.err.println( "### no service manager instance for late init of singleton instance \"" + rName + "\"!" );
149                             }
150                         }
151                         else
152                         {
153                             XSingleComponentFactory xCompFac =
154                                 UnoRuntime.queryInterface(
155                                     XSingleComponentFactory.class, entry.m_lateInit );
156                             if (xCompFac != null)
157                             {
158                                 xInstance = xCompFac.createInstanceWithContext( this );
159                             }
160                             else
161                             {
162                                 if (DEBUG)
163                                     System.err.println( "### neither service name nor service factory given for late init of singleton instance \"" + rName + "\"!" );
164                             }
165                         }
166                     }
167                     catch (com.sun.star.uno.Exception exc)
168                     {
169                         if (DEBUG)
170                             System.err.println( "### exception occured on late init of singleton instance \"" + rName + "\": " + exc.getMessage() );
171                     }
172 
173                     if (xInstance != null)
174                     {
175                         synchronized (entry)
176                         {
177                             if (entry.m_lateInit != null)
178                             {
179                                 entry.m_value = xInstance;
180                                 entry.m_lateInit = null;
181                             }
182                             else // inited in the meantime
183                             {
184                                 // dispose fresh service instance
185                                 XComponent xComp = UnoRuntime.queryInterface(
186                                     XComponent.class, xInstance );
187                                 if (xComp != null)
188                                 {
189                                     xComp.dispose();
190                                 }
191                             }
192                         }
193                     }
194                     else
195                     {
196                         if (DEBUG)
197                             System.err.println( "### failed late init of singleton instance \"" + rName + "\"!" );
198                     }
199                 }
200                 return entry.m_value;
201             }
202             else // direct value in map
203             {
204                 return o;
205             }
206         }
207         else if (m_xDelegate != null)
208         {
209             return m_xDelegate.getValueByName( rName );
210         }
211         else
212         {
213             return Any.VOID;
214         }
215     }
216     //______________________________________________________________________________________________
217     public XMultiComponentFactory getServiceManager()
218     {
219         return m_xSMgr;
220     }
221 
222     // XComponent impl
223     //______________________________________________________________________________________________
224     public void dispose()
225     {
226         if (DEBUG)
227             System.err.print( "> disposing context " + this );
228 
229         // fire events
230         EventObject evt = new EventObject( this );
231         Enumeration eventListener = m_eventListener.elements();
232         while (eventListener.hasMoreElements())
233         {
234             XEventListener listener = (XEventListener)eventListener.nextElement();
235             listener.disposing( evt );
236         }
237         m_eventListener.removeAllElements();
238 
239         XComponent tdmgr = null;
240         // dispose values, then service manager, then typdescription manager
241         Enumeration keys = m_table.keys();
242         while (keys.hasMoreElements())
243         {
244             String name = (String)keys.nextElement();
245             if (! name.equals( SMGR_NAME ))
246             {
247                 Object o = m_table.get( name );
248                 if (o instanceof ComponentContextEntry)
249                 {
250                     o = ((ComponentContextEntry)o).m_value;
251                 }
252 
253                 XComponent xComp = UnoRuntime.queryInterface( XComponent.class, o );
254                 if (xComp != null)
255                 {
256                     if (name.equals( TDMGR_NAME ))
257                     {
258                         tdmgr = xComp;
259                     }
260                     else
261                     {
262                         xComp.dispose();
263                     }
264                 }
265             }
266         }
267         m_table.clear();
268 
269         // smgr
270         if (m_bDisposeSMgr)
271         {
272             XComponent xComp = UnoRuntime.queryInterface(
273                 XComponent.class, m_xSMgr );
274             if (xComp != null)
275             {
276                 xComp.dispose();
277             }
278         }
279         m_xSMgr = null;
280 
281         // tdmgr
282         if (tdmgr != null)
283         {
284             tdmgr.dispose();
285         }
286 
287         if (DEBUG)
288             System.err.println( "... finished" );
289     }
290     //______________________________________________________________________________________________
291     public void addEventListener( XEventListener xListener )
292     {
293         if (xListener == null)
294         	throw new com.sun.star.uno.RuntimeException( "Listener must not be null" );
295   		if (m_eventListener.contains( xListener ))
296   			throw new com.sun.star.uno.RuntimeException( "Listener already registred." );
297 
298        	m_eventListener.addElement( xListener );
299     }
300     //______________________________________________________________________________________________
301     public void removeEventListener( XEventListener xListener )
302     {
303         if (xListener == null)
304         	throw new com.sun.star.uno.RuntimeException( "Listener must not be null" );
305   		if (! m_eventListener.contains( xListener ))
306   			throw new com.sun.star.uno.RuntimeException( "Listener is not registered." );
307 
308         m_eventListener.removeElement( xListener );
309     }
310 }
311