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