Source for gnu.java.rmi.activation.ActivationSystemTransient

   1: /* ActivationSystemTransient.java -- The transient RMI object activation system.
   2:    Copyright (C) 2006 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package gnu.java.rmi.activation;
  40: 
  41: import java.rmi.MarshalledObject;
  42: import java.rmi.RemoteException;
  43: import java.rmi.activation.ActivationDesc;
  44: import java.rmi.activation.ActivationException;
  45: import java.rmi.activation.ActivationGroup;
  46: import java.rmi.activation.ActivationGroupDesc;
  47: import java.rmi.activation.ActivationGroupID;
  48: import java.rmi.activation.ActivationID;
  49: import java.rmi.activation.ActivationInstantiator;
  50: import java.rmi.activation.ActivationMonitor;
  51: import java.rmi.activation.ActivationSystem;
  52: import java.rmi.activation.Activator;
  53: import java.rmi.activation.UnknownGroupException;
  54: import java.rmi.activation.UnknownObjectException;
  55: import java.util.HashMap;
  56: import java.util.Hashtable;
  57: import java.util.Iterator;
  58: import java.util.Map;
  59: 
  60: /**
  61:  * Provides the default transient activation system.
  62:  *
  63:  * @author Audrius Meskauskas (audriusa@bioinformatics.org)
  64:  */
  65: public class ActivationSystemTransient
  66:     extends DefaultActivationSystem
  67:     implements ActivationSystem, ActivationMonitor, Activator
  68: {
  69:   /**
  70:    * Maps group identifiers into group descriptions.
  71:    */
  72:   protected final BidiTable groupDescs;
  73: 
  74:   /**
  75:    * Maps object identifiers into object activation descriptions
  76:    */
  77:   protected final BidiTable descriptions;
  78: 
  79:   /**
  80:    * Maps group identifiers into already activated groups.
  81:    */
  82:   protected transient final Map groupInstantiators = new Hashtable();
  83: 
  84:   /**
  85:    * The cache of the activated objects, maps activation ids to remote
  86:    * object stubs.
  87:    */
  88:   protected transient final Map activatedObjects = new HashMap();
  89: 
  90:   /**
  91:    * The object incarnation counter.
  92:    */
  93:   static long groupIncarnations = 0;
  94: 
  95:   /**
  96:    * The singleton of this activation system
  97:    */
  98:   static ActivationSystem singleton;
  99: 
 100:   /**
 101:    * Set to true to print the event messages to console.
 102:    */
 103:   public static boolean debug = false;
 104: 
 105: 
 106:   /**
 107:    * Creates the group which uses the given maps to store the data.
 108:    */
 109:   protected ActivationSystemTransient(BidiTable objectDescriptions,
 110:                                       BidiTable groupDescriptiopns)
 111:   {
 112:     descriptions = objectDescriptions;
 113:     groupDescs = groupDescriptiopns;
 114:   }
 115: 
 116:   /**
 117:    * Creates the group with transient maps.
 118:    */
 119:   protected ActivationSystemTransient()
 120:   {
 121:     this (new BidiTable(), new BidiTable());
 122:   }
 123: 
 124:   public static ActivationSystem getInstance()
 125:   {
 126:     if (singleton == null)
 127:       singleton = new ActivationSystemTransient();
 128:     return singleton;
 129:   }
 130: 
 131:   /**
 132:    * Activate the given object (try cache first if force = false)
 133:    */
 134:   public MarshalledObject activate(ActivationID id, boolean force)
 135:       throws ActivationException, UnknownObjectException, RemoteException
 136:   {
 137:     if (! force)
 138:       {
 139:         synchronized (activatedObjects)
 140:           {
 141:             MarshalledObject object = (MarshalledObject) activatedObjects.get(id);
 142:             if (object != null)
 143:               return object;
 144:           }
 145:       }
 146: 
 147:     ActivationDesc desc = (ActivationDesc) descriptions.get(id);
 148:     if (desc == null)
 149:       throw new UnknownObjectException("Activating unknown object  "+
 150:                                        id == null ? "null" : id.toString());
 151: 
 152:     ActivationInstantiator group =
 153:       (ActivationInstantiator) groupInstantiators.get(desc.getGroupID());
 154: 
 155:     if (group == null)
 156:       {
 157:         // The group is not active - must be activated.
 158:         ActivationGroupID gid = desc.getGroupID();
 159:         ActivationGroupDesc adesc = (ActivationGroupDesc) groupDescs.get(gid);
 160: 
 161:         if (adesc == null)
 162:           throw new UnknownGroupException("Activating unknown group "
 163:                                           + gid + " for "+ id+" this "+this);
 164: 
 165:         synchronized (ActivationSystemTransient.class)
 166:           {
 167:             groupIncarnations++;
 168:           }
 169: 
 170:         group = ActivationGroup.createGroup(gid, adesc, groupIncarnations);
 171:         activeGroup(gid, group, groupIncarnations);
 172:       }
 173: 
 174:     MarshalledObject object = group.newInstance(id, desc);
 175: 
 176:     synchronized (activatedObjects)
 177:       {
 178:         activatedObjects.put(id, object);
 179:       }
 180:     return object;
 181:   }
 182: 
 183:   /**
 184:    * Returns the activation monitor (THIS) and remebers the instantiator, used
 185:    * by that group.
 186:    */
 187:   public ActivationMonitor activeGroup(ActivationGroupID id,
 188:                                        ActivationInstantiator group,
 189:                                        long incarnation)
 190:       throws UnknownGroupException, ActivationException, RemoteException
 191:   {
 192:     groupInstantiators.put(id, group);
 193:     return this;
 194:   }
 195: 
 196:   /**
 197:    * Get the activation descriptor for the given activation id.
 198:    *
 199:    * @return the activation descriptor, never null.
 200:    * @throws UnknownObjectException if such object is unknown.
 201:    */
 202:   public ActivationDesc getActivationDesc(ActivationID id)
 203:       throws ActivationException, UnknownObjectException, RemoteException
 204:   {
 205:     ActivationDesc desc = (ActivationDesc) descriptions.get(id);
 206:     if (desc == null)
 207:       throw new UnknownObjectException("No desc for "+
 208:                                        id == null ? "null" : id.toString());
 209:     return desc;
 210:   }
 211: 
 212:   /**
 213:    * Get the descriptor of the given activation group.
 214:    *
 215:    * @return the activation group descriptor, never null.
 216:    * @throws UnknownGroupException if such group is unknown
 217:    */
 218:   public ActivationGroupDesc getActivationGroupDesc(ActivationGroupID groupId)
 219:       throws ActivationException, UnknownGroupException, RemoteException
 220:   {
 221:     ActivationGroupDesc desc = (ActivationGroupDesc) groupDescs.get(groupId);
 222:     if (desc == null)
 223:       throw new UnknownGroupException(groupId == null ? "null"
 224:                                                      : groupId.toString());
 225:     return desc;
 226:   }
 227: 
 228:   /**
 229:    * Create the activation group id and put this id-descriptor combination into
 230:    * the group map. The new ID will only be created if this description has not
 231:    * already been registered, otherwise the id of the registered description
 232:    * will be returned.
 233:    */
 234:   public ActivationGroupID registerGroup(ActivationGroupDesc groupDesc)
 235:       throws ActivationException, RemoteException
 236:   {
 237:     ActivationGroupID id = (ActivationGroupID) groupDescs.getKey(groupDesc);
 238:     if (id == null)
 239:       {
 240:         id = new ActivationGroupID(this);
 241:         groupDescs.put(id, groupDesc);
 242:       }
 243:     if (debug)
 244:       System.out.println("Register group " + id +":"+groupDesc+" this "+this);
 245: 
 246:     return id;
 247:   }
 248: 
 249:   /**
 250:    * Create the object activation id and put this id-descriptor combination into
 251:    * the group map. The new ID will only be created if this description has not
 252:    * already been registered, otherwise the id of the registered description
 253:    * will be returned.
 254:    */
 255:   public ActivationID registerObject(ActivationDesc desc)
 256:       throws ActivationException, UnknownGroupException, RemoteException
 257:   {
 258:     ActivationID id = (ActivationID) descriptions.getKey(desc);
 259:     if (id == null)
 260:       {
 261:         id = new ActivationID(this);
 262:         descriptions.put(id, desc);
 263:       }
 264: 
 265:     if (debug)
 266:       System.out.println("Register object " + id +":"+desc+" this "+this);
 267: 
 268:     return id;
 269:   }
 270: 
 271:   /**
 272:    * Replace the activation descriptor, return the previous descriptor.
 273:    */
 274:   public ActivationDesc setActivationDesc(ActivationID id, ActivationDesc desc)
 275:       throws ActivationException, UnknownObjectException,
 276:       UnknownGroupException, RemoteException
 277:   {
 278:     ActivationDesc prev = getActivationDesc(id);
 279:     descriptions.put(id, desc);
 280:     return prev;
 281:   }
 282: 
 283:   /**
 284:    * Replace the activation group descriptor, return the previous descriptor.
 285:    */
 286:   public ActivationGroupDesc setActivationGroupDesc(
 287:                                                     ActivationGroupID groupId,
 288:                                                     ActivationGroupDesc groupDesc)
 289:       throws ActivationException, UnknownGroupException, RemoteException
 290:   {
 291:     ActivationGroupDesc prev = getActivationGroupDesc(groupId);
 292:     groupDescs.put(groupId, groupDesc);
 293:     return prev;
 294:   }
 295: 
 296:   /**
 297:    * Calls .shutdown on all bidirectional tables (has no effect if these
 298:    * table are not persistent).
 299:    */
 300:   public void shutdown() throws RemoteException
 301:   {
 302:     descriptions.shutdown();
 303:     groupDescs.shutdown();
 304:   }
 305: 
 306:   /**
 307:    * Remove the group from the group map
 308:    */
 309:   public void unregisterGroup(ActivationGroupID groupId) throws ActivationException,
 310:       UnknownGroupException, RemoteException
 311:   {
 312:     if (! groupDescs.containsKey(groupId))
 313:       throw new UnknownGroupException("Unknown group "+groupId);
 314: 
 315:     groupDescs.removeKey(groupId);
 316:     groupInstantiators.remove(groupId);
 317:   }
 318: 
 319:   /**
 320:    * Remove the object id from the active object and description maps.
 321:    */
 322:   public void unregisterObject(ActivationID id) throws ActivationException,
 323:       UnknownObjectException, RemoteException
 324:   {
 325:     if (! descriptions.containsKey(id))
 326:       throw new UnknownObjectException("Unregistering unknown object");
 327:     descriptions.removeKey(id);
 328: 
 329:     synchronized (activatedObjects)
 330:       {
 331:         activatedObjects.remove(id);
 332:       }
 333:   }
 334: 
 335:   /**
 336:    * Put the object into active object map.
 337:    */
 338:   public void activeObject(ActivationID id, MarshalledObject obj)
 339:       throws UnknownObjectException, RemoteException
 340:   {
 341:     if (! descriptions.containsKey(id))
 342:       throw new UnknownObjectException("Activating unknown object "+
 343:                                         id+" this "+this);
 344:     try
 345:       {
 346:         synchronized (activatedObjects)
 347:           {
 348:             activatedObjects.put(id, obj.get());
 349:           }
 350:       }
 351:     catch (RemoteException e)
 352:       {
 353:         throw e;
 354:       }
 355:     catch (Exception e)
 356:       {
 357:         UnknownObjectException un = new UnknownObjectException(
 358:           "Cannot get Remote for MarshalledObject of "+id);
 359:         un.detail = e;
 360:         throw un;
 361:       }
 362:   }
 363: 
 364:   /**
 365:    * Check if the group is known. Remove all active objects, belonging to
 366:    * that group, from the active object cache.
 367:    */
 368:   public void inactiveGroup(ActivationGroupID groupId, long incarnation)
 369:       throws UnknownGroupException, RemoteException
 370:   {
 371:     if (! groupInstantiators.containsKey(groupId))
 372:       throw new UnknownGroupException("Inactivating unkwnon group");
 373: 
 374:     groupInstantiators.remove(groupId);
 375: 
 376:     // Remove all members of this group from the cache.
 377:     synchronized (activatedObjects)
 378:     {
 379:       Iterator iter = activatedObjects.keySet().iterator();
 380:       ActivationID id;
 381:       ActivationDesc desc;
 382:       while (iter.hasNext())
 383:         {
 384:           id = (ActivationID) iter.next();
 385:           desc = (ActivationDesc) descriptions.get(id);
 386:           if (desc.getGroupID().equals(groupId))
 387:             activatedObjects.remove(id);
 388:         }
 389:     }
 390:   }
 391: 
 392:   /**
 393:    * Removes this id from the active object cache.
 394:    */
 395:   public void inactiveObject(ActivationID id) throws UnknownObjectException,
 396:       RemoteException
 397:   {
 398:     if (! descriptions.containsKey(id))
 399:       throw new UnknownObjectException("Inactivating unknown object");
 400: 
 401:     synchronized (activatedObjects)
 402:       {
 403:         activatedObjects.remove(id);
 404:       }
 405:   }
 406: }