KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jacorb > poa > AOM


1 package org.jacorb.poa;
2
3 /*
4  * JacORB - a free Java ORB
5  *
6  * Copyright (C) 1997-2004 Gerald Brose.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the Free
20  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */

22
23 import java.util.*;
24
25 import org.jacorb.poa.POA;
26 import org.jacorb.poa.except.POAInternalError;
27 import org.jacorb.poa.util.ByteArrayKey;
28 import org.jacorb.poa.util.POAUtil;
29 import org.jacorb.poa.util.StringPair;
30
31 import org.omg.PortableServer.POAPackage.ObjectAlreadyActive JavaDoc;
32 import org.omg.PortableServer.POAPackage.ObjectNotActive JavaDoc;
33 import org.omg.PortableServer.POAPackage.ServantAlreadyActive JavaDoc;
34 import org.omg.PortableServer.Servant JavaDoc;
35 import org.omg.PortableServer.ServantActivator JavaDoc;
36
37 import org.apache.avalon.framework.logger.Logger;
38
39 /**
40  * This class maps object id's to servants and vice versa.
41  * A oid/servant pair can be added/removed using add(),remove().
42  * The data can be retrieved using getServant() or getObjectId().
43  *
44  * @author Reimo Tiedemann, FU Berlin
45  * @version $Id: AOM.java,v 1.29 2004/05/06 12:40:00 nicolas Exp $
46  */

47
48 public class AOM
49 {
50     private AOMListener aomListener;
51
52     private boolean unique;
53     private boolean singleThreaded;
54     private Logger logger;
55
56     // an ObjectID can appear only once, but an servant can have multiple ObjectId's
57
// if MULTIPLE_ID is set
58
private Hashtable objectMap = new Hashtable(); // oid -> servant
59

60     // only meaningful if UNIQUE_ID is set
61
// only for performance improvements (brose: is that still true?)
62
private Hashtable servantMap; // servant -> oid
63

64     // for synchronisation of servant activator calls
65
private Vector etherealisationList = new Vector();
66     private Vector incarnationList = new Vector();
67
68     private Vector deactivationList = new Vector();
69     /** a lock to protect two consecutive operations on the list, used
70         in remove() */

71     private Object JavaDoc deactivationListLock = new Object JavaDoc();
72
73     private AOM()
74     {
75     }
76
77     protected AOM( boolean _unique,
78                    boolean single_threaded,
79                    Logger _logger
80                  )
81     {
82         unique = _unique;
83         singleThreaded = single_threaded;
84         logger = _logger;
85
86         if (unique)
87         {
88             servantMap = new Hashtable();
89         }
90     }
91
92
93     /**
94      * <code>add</code> is called by the POA when activating an object
95      * to add a Servant into the Active Object Map.
96      *
97      * @param oid a <code>byte[]</code>, the id to use.
98      * @param servant a <code>Servant</code>, the servant to store.
99      * @exception ObjectAlreadyActive if an error occurs
100      * @exception ServantAlreadyActive if an error occurs
101      */

102     protected synchronized void add( byte[] oid, Servant JavaDoc servant )
103         throws ObjectAlreadyActive JavaDoc, ServantAlreadyActive JavaDoc
104     {
105         ByteArrayKey oidbak = new ByteArrayKey (oid);
106
107         /* an inCarnation and activation with the same oid has
108            priority, a reactivation for the same oid blocks until
109            etherealization is complete */

110
111         while (incarnationList.contains(oidbak) ||
112                etherealisationList.contains(oidbak) ||
113                // This is to check whether we are currently deactivating an
114
// object with the same id - if so, wait for the deactivate
115
// thread to complete.
116
deactivationList.contains( oidbak ) ||
117                // This is to check whether we are attempting to reactivate
118
// a servant that is currently being deactivated with another ID.
119
(
120                    servantMap != null &&
121                    servantMap.get( servant ) != null &&
122                    deactivationList.contains((ByteArrayKey)servantMap.get( servant ))
123                ))
124         {
125             try
126             {
127                 wait();
128             }
129             catch (InterruptedException JavaDoc e)
130             {
131             }
132         }
133
134         if (objectMap.containsKey(oidbak))
135             throw new ObjectAlreadyActive JavaDoc();
136
137         if (unique && servantMap.containsKey(servant))
138             throw new ServantAlreadyActive JavaDoc();
139
140         /* this is the actual object activation: */
141
142         objectMap.put(oidbak, servant);
143
144         if ( unique )
145         {
146             servantMap.put(servant, oidbak);
147         }
148
149         if (logger.isInfoEnabled())
150         {
151             logger.info("oid: " + POAUtil.convert(oid) +
152                         "object is activated");
153         }
154
155         // notify an aom listener
156
if (aomListener != null)
157             aomListener.objectActivated(oid, servant, objectMap.size());
158     }
159
160
161     protected synchronized void addAOMListener(AOMListener listener)
162     {
163         aomListener = EventMulticaster.add(aomListener, listener);
164     }
165
166
167     boolean isDeactivating (ByteArrayKey oid)
168     {
169         return deactivationList.contains (oid);
170     }
171
172
173     protected boolean contains(Servant JavaDoc servant)
174     {
175         if (unique)
176         {
177             return servantMap.containsKey(servant);
178         }
179         else
180         {
181             return objectMap.contains(servant);
182         }
183     }
184
185
186     protected synchronized StringPair[] deliverContent()
187     {
188         StringPair[] result = new StringPair[objectMap.size()];
189         ByteArrayKey oidbak;
190         Enumeration en = objectMap.keys();
191
192         for ( int i = 0; i < result.length; i++ )
193         {
194             oidbak = (ByteArrayKey) en.nextElement();
195             result[i] = new StringPair
196             (
197                 oidbak.toString(),
198                 objectMap.get(oidbak).getClass().getName()
199             );
200         }
201         return result;
202
203     }
204
205     protected byte[] getObjectId(Servant JavaDoc servant)
206     {
207         if (!unique)
208             throw new POAInternalError("error: not UNIQUE_ID policy (getObjectId)");
209
210         ByteArrayKey oidbak = (ByteArrayKey)servantMap.get(servant);
211
212         if (oidbak != null)
213             return oidbak.getBytes();
214
215         return null;
216     }
217
218
219
220     protected Servant JavaDoc getServant(byte[] oid)
221     {
222         return (Servant JavaDoc) objectMap.get( new ByteArrayKey( oid ) );
223     }
224
225
226
227
228     protected synchronized Servant JavaDoc incarnate( byte[] oid,
229                                               ServantActivator JavaDoc servant_activator,
230                                               org.omg.PortableServer.POA JavaDoc poa )
231         throws org.omg.PortableServer.ForwardRequest JavaDoc
232     {
233         ByteArrayKey oidbak = new ByteArrayKey( oid );
234         Servant JavaDoc servant = null;
235
236         if (logger.isInfoEnabled())
237         {
238             logger.info( "oid: " + POAUtil.convert(oid) +
239                         "incarnate");
240         }
241
242         /* all invocations of incarnate on the servant manager are serialized */
243         /* all invocations of etherealize on the servant manager are serialized */
244         /* invocations of incarnate and etherialize are mutually exclusive */
245
246         while (!incarnationList.isEmpty() || !etherealisationList.isEmpty())
247         {
248             try
249             {
250                 wait();
251             }
252             catch (InterruptedException JavaDoc e) {
253             }
254         }
255
256         /* another thread was faster, the incarnation is unnecessary now */
257         if (objectMap.containsKey(oidbak))
258         {
259             return (Servant JavaDoc) objectMap.get(oidbak);
260         }
261
262         /* servant incarnation */
263
264         incarnationList.addElement(oidbak);
265         try
266         {
267             servant = servant_activator.incarnate(oid, poa);
268         }
269         finally
270         {
271             incarnationList.removeElement(oidbak);
272             notifyAll();
273         }
274
275         if (servant == null)
276         {
277             if (logger.isInfoEnabled())
278             {
279                 logger.info("oid: " + POAUtil.convert(oid) +
280                             "servant is not incarnated (incarnate returns null)");
281             }
282             return null;
283         }
284
285         if (unique && servantMap.containsKey(servant))
286         {
287             if (logger.isInfoEnabled())
288             {
289                 logger.info("oid: " + POAUtil.convert(oid) +
290                             "servant is not incarnated (unique_id policy is violated)");
291             }
292             return null;
293         }
294
295         if (logger.isDebugEnabled())
296         {
297             logger.debug("oid: " + POAUtil.convert(oid) +
298                          "servant is incarnated");
299         }
300         
301         // notify an aom listener
302
if (aomListener != null)
303             aomListener.servantIncarnated(oid, servant);
304         
305         /* object activation */
306         
307         try
308         {
309             add(oid, servant);
310         }
311         catch (ObjectAlreadyActive JavaDoc e)
312         {
313             throw new POAInternalError("error: object already active (AOM.incarnate)");
314         }
315         catch (ServantAlreadyActive JavaDoc e)
316         {
317             throw new POAInternalError("error: servant already active (AOM.incarnate)");
318         }
319         return servant;
320     }
321
322     protected void remove( byte[] oid,
323                            RequestController requestController,
324                            ServantActivator JavaDoc servantActivator,
325                            POA poa,
326                            boolean cleanupInProgress)
327         throws ObjectNotActive JavaDoc
328     {
329         ByteArrayKey oidbak = new ByteArrayKey( oid );
330
331         // check that the same oid is not already being deactivated
332
// (this must be synchronized to avoid having two independent
333
// threads register the same oid)
334
synchronized( deactivationListLock )
335         {
336             if ( !objectMap.containsKey( oidbak ) ||
337                  deactivationList.contains( oidbak ) )
338             {
339                 throw new ObjectNotActive JavaDoc();
340             }
341
342             deactivationList.addElement(oidbak);
343         }
344
345         final byte[] oid_ = oid;
346         final RequestController requestController_ = requestController;
347         final ServantActivator JavaDoc servantActivator_ = servantActivator;
348         final POA poa_ = poa;
349         final boolean cleanupInProgress_ = cleanupInProgress;
350
351         Thread JavaDoc thread = new Thread JavaDoc("AOM_RemovalThread")
352         {
353             public void run()
354             {
355                 _remove(
356                     oid_,
357                     requestController_,
358                     servantActivator_,
359                     poa_,
360                     cleanupInProgress_
361                        );
362             }
363         };
364
365         thread.start();
366     }
367
368
369     /**
370      * <code>_remove</code> is spawned by remove to allow deactivate_object
371      * to return immediately.
372      *
373      * @param oid a <code>byte[]</code>, the id to use.
374      * @param requestController a <code>RequestController</code> value
375      * @param servantActivator a <code>ServantActivator</code> value
376      * @param poa a <code>POA</code> value
377      * @param cleanupInProgress a <code>boolean</code> value
378      */

379     private void _remove( byte[] oid,
380                           RequestController requestController,
381                           ServantActivator JavaDoc servantActivator,
382                           POA poa,
383                           boolean cleanupInProgress)
384     {
385         ByteArrayKey oidbak = new ByteArrayKey( oid );
386         Servant JavaDoc servant = null;
387
388         if (!objectMap.containsKey(oidbak))
389         {
390             // should not happen but ...
391
deactivationList.removeElement(oidbak);
392             return;
393         }
394
395         // wait for request completion on this object (see freeObject below)
396
if ( requestController != null)
397             requestController.waitForObjectCompletion(oid);
398
399         synchronized (this)
400         {
401             if ((servant = (Servant JavaDoc)objectMap.get(oidbak)) == null) {
402                 return;
403             }
404
405             /* object deactivation */
406
407             objectMap.remove(oidbak);
408
409             if (unique)
410             {
411                 servantMap.remove(servant);
412             }
413
414             // Wait to remove the oid from the deactivationList here so that the
415
// object map can be cleared out first. This ensures we don't
416
// reactivate an object we're currently deactivating.
417
deactivationList.removeElement(oidbak);
418
419             if (logger.isInfoEnabled())
420             {
421                 logger.info("oid: " + POAUtil.convert(oid) +
422                             "object is deactivated");
423             }
424
425             // notify an aom listener
426
if (aomListener != null)
427                 aomListener.objectDeactivated(oid, servant, objectMap.size());
428
429             if (servantActivator == null)
430             {
431                 requestController.freeObject(oid);
432                 // Tell anyone waiting we're done now.
433
notifyAll();
434                 return;
435             }
436
437             /* servant etherealization */
438
439             /* all invocations of incarnate on the servant manager are
440                serialized, all invocations of etherealize on the
441                servant manager are serialized, invocations of incarnate
442                and etherialize are mutually exclusive */

443
444             while (!incarnationList.isEmpty() || !etherealisationList.isEmpty())
445             {
446                 try
447                 {
448                     wait();
449                 }
450                 catch (InterruptedException JavaDoc e)
451                 {
452                 }
453             }
454             etherealisationList.addElement(oidbak);
455
456             try
457             {
458                 servantActivator.etherealize
459                 (
460                     oid,
461                     poa,
462                     servant,
463                     cleanupInProgress,
464                     contains(servant)
465                 );
466
467                 if (logger.isInfoEnabled())
468                 {
469                     logger.info("oid: " + POAUtil.convert(oid) +
470                                 "servant is etherealized");
471                 }
472
473                 // notify an aom listener
474

475                 if (aomListener != null)
476                     aomListener.servantEtherialized(oid, servant);
477
478             }
479             catch (org.omg.CORBA.SystemException JavaDoc e)
480             {
481                 if (logger.isWarnEnabled())
482                 {
483                     logger.info("oid: " + POAUtil.convert(oid) +
484                                 "exception occurred during servant etherialisation: " + e.getMessage()
485                                 );
486                 }
487             }
488             finally
489             {
490                 etherealisationList.removeElement(oidbak);
491                 notifyAll();
492             }
493
494             // unregister the object from deactivation list
495
if (requestController != null)
496                 requestController.freeObject(oid);
497         }
498     }
499
500     protected void removeAll( ServantActivator JavaDoc servant_activator,
501                               POA poa,
502                               boolean cleanup_in_progress )
503     {
504         byte[] oid;
505         Enumeration en = objectMap.keys();
506         while (en.hasMoreElements())
507         {
508             oid = ((ByteArrayKey) en.nextElement()).getBytes();
509             _remove(oid, null, servant_activator, poa, cleanup_in_progress);
510         }
511     }
512
513     protected synchronized void removeAOMListener(AOMListener listener)
514     {
515         aomListener = EventMulticaster.remove(aomListener, listener);
516     }
517
518     protected int size()
519     {
520         return objectMap.size();
521     }
522 }
523
Popular Tags