Source for java.rmi.activation.ActivationGroupDesc

   1: /* ActivationGroupDesc.java -- the RMI activation group descriptor
   2:    Copyright (c) 1996, 1997, 1998, 1999, 2004, 2006
   3:    Free Software Foundation, Inc.
   4: 
   5: This file is part of GNU Classpath.
   6: 
   7: GNU Classpath is free software; you can redistribute it and/or modify
   8: it under the terms of the GNU General Public License as published by
   9: the Free Software Foundation; either version 2, or (at your option)
  10: any later version.
  11: 
  12: GNU Classpath is distributed in the hope that it will be useful, but
  13: WITHOUT ANY WARRANTY; without even the implied warranty of
  14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15: General Public License for more details.
  16: 
  17: You should have received a copy of the GNU General Public License
  18: along with GNU Classpath; see the file COPYING.  If not, write to the
  19: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  20: 02110-1301 USA.
  21: 
  22: Linking this library statically or dynamically with other modules is
  23: making a combined work based on this library.  Thus, the terms and
  24: conditions of the GNU General Public License cover the whole
  25: combination.
  26: 
  27: As a special exception, the copyright holders of this library give you
  28: permission to link this library with independent modules to produce an
  29: executable, regardless of the license terms of these independent
  30: modules, and to copy and distribute the resulting executable under
  31: terms of your choice, provided that you also meet, for each linked
  32: independent module, the terms and conditions of the license of that
  33: module.  An independent module is a module which is not derived from
  34: or based on this library.  If you modify this library, you may extend
  35: this exception to your version of the library, but you are not
  36: obligated to do so.  If you do not wish to do so, delete this
  37: exception statement from your version. */
  38: 
  39: 
  40: package java.rmi.activation;
  41: 
  42: import gnu.java.rmi.activation.DefaultActivationGroup;
  43: 
  44: import java.io.Serializable;
  45: import java.rmi.MarshalledObject;
  46: import java.util.Arrays;
  47: import java.util.Enumeration;
  48: import java.util.Iterator;
  49: import java.util.Properties;
  50: import java.util.TreeSet;
  51: import java.util.zip.Adler32;
  52: 
  53: /**
  54:  * Contains information, necessary to create of recreate the activation objects.
  55:  * The group descriptor contains:
  56:  * <ul>
  57:  * <li>The name of the group's class. This class is derived from the
  58:  * {@link ActivationGroup}.</li>
  59:  * <li>The group class code location.</li>
  60:  * <li>The marshalled object that contains the group specific initialization
  61:  * information</li>
  62:  * </ul>
  63:  * The groups are created by the {@link ActivationGroup#createGroup} method that
  64:  * expectes the group class to have the two parameter constructor, the first
  65:  * parameter being the {@link ActivationGroupID} and the second the
  66:  * {@link MarshalledObject}.
  67:  *
  68:  * @author Audrius Meskauskas (audriusa@bioinformatics.org) (from stub)
  69:  */
  70: public final class ActivationGroupDesc
  71:     implements Serializable
  72: {
  73:   /**
  74:    * Contains the startup options for the {@link ActivationGroup}
  75:    * implementations. Allows to override system properties and specify other
  76:    * options for the implementation groups.
  77:    *
  78:    * @author Audrius Meskauskas (audriusa@bioinformatics.org) (from stub)
  79:    */
  80:   public static class CommandEnvironment
  81:       implements Serializable
  82:   {
  83: 
  84:     /**
  85:      * Use the SVUID for interoperability.
  86:      */
  87:     static final long serialVersionUID = 6165754737887770191L;
  88: 
  89:     /**
  90:      * The zero size string array used as argv value when null is passed.
  91:      */
  92:     private static final String[] NO_ARGS = new String[0];
  93: 
  94:     /**
  95:      * The path to the java executable (or null for using default jre).
  96:      */
  97:     final String command;
  98: 
  99:     /**
 100:      * The extra parameters (may be empty array but never null).
 101:      */
 102:     final String[] options;
 103: 
 104:     /**
 105:      * Create the new command environment.
 106:      *
 107:      * @param commandPatch the full path (and name) to the java executable of
 108:      *          null for using the default executable.
 109:      * @param args extra options that will be used when creating the activation
 110:      *          group. Null has the same effect as the empty list.
 111:      */
 112:     public CommandEnvironment(String commandPatch, String[] args)
 113:     {
 114:       command = commandPatch;
 115:       if (args != null)
 116:         options = args;
 117:       else
 118:         options = NO_ARGS;
 119:     }
 120: 
 121:     /**
 122:      * Get the path to the java executable.
 123:      *
 124:      * @return the path to the java executable or null for using the default
 125:      * jre.
 126:      */
 127:     public String getCommandPath()
 128:     {
 129:       return command;
 130:     }
 131: 
 132:     /**
 133:      * Get the additional command options.
 134:      *
 135:      * @return the command options array, may be empty string
 136:      */
 137:     public String[] getCommandOptions()
 138:     {
 139:       return options;
 140:     }
 141: 
 142:     /**
 143:      * Compare for content equality.
 144:      */
 145:     public boolean equals(Object obj)
 146:     {
 147:       if (obj instanceof CommandEnvironment)
 148:         {
 149:           CommandEnvironment that = (CommandEnvironment) obj;
 150: 
 151:           if (command == null || that.command == null)
 152:             {
 153:               // Use direct comparison if null is involved.
 154:               if (command != that.command)
 155:                 return false;
 156:             }
 157:           else
 158:             {
 159:               // Use .equals if null is not involved.
 160:               if (! this.command.equals(that.command))
 161:                 return false;
 162:             }
 163: 
 164:           return Arrays.equals(options, that.options);
 165:         }
 166:       else
 167:         return false;
 168:     }
 169: 
 170:     /**
 171:      * Get the hash code.
 172:      */
 173:     public int hashCode()
 174:     {
 175:       int h = command == null ? 0 : command.hashCode();
 176:       for (int i = 0; i < options.length; i++)
 177:         h ^= options[i].hashCode();
 178: 
 179:       return h;
 180:     }
 181:   }
 182: 
 183:   /**
 184:    * Use the SVUID for interoperability.
 185:    */
 186:   static final long serialVersionUID = - 4936225423168276595L;
 187: 
 188:   /**
 189:    * The group class name or null for the default group class implementation.
 190:    */
 191:   final String className;
 192: 
 193:   /**
 194:    * The group class download location URL (codebase), ignored by the
 195:    * default implementation.
 196:    */
 197:   final String location;
 198: 
 199:   /**
 200:    * The group initialization data.
 201:    */
 202:   final MarshalledObject<?> data;
 203: 
 204:   /**
 205:    * The path to the group jre and the parameters of this jre, may be
 206:    * null for the default jre.
 207:    */
 208:   final ActivationGroupDesc.CommandEnvironment env;
 209: 
 210:   /**
 211:    * The properties that override the system properties.
 212:    */
 213:   final Properties props;
 214: 
 215:   /**
 216:    * The cached hash code.
 217:    */
 218:   transient long hash;
 219: 
 220:   /**
 221:    * Create the new activation group descriptor that will use the default
 222:    * activation group implementation with the given properties and
 223:    * environment.
 224:    *
 225:    * @param aProperties the properties that override the system properties
 226:    * @param environment the command line (and parameters), indicating, where to
 227:    *          find the jre executable and with that parameters to call it. May
 228:    *          be null if the default executable should be used. In this case,
 229:    *          the activation group with the null name (the system default group)
 230:    *          will be created.
 231:    */
 232:   public ActivationGroupDesc(Properties aProperties,
 233:                              ActivationGroupDesc.CommandEnvironment environment)
 234:   {
 235:     this(DefaultActivationGroup.class.getName(), null, null, aProperties,
 236:          environment);
 237:   }
 238: 
 239:   /**
 240:    * Create the new activation group descriptor.
 241:    *
 242:    * @param aClassName the name of the group implementation class. The null
 243:    *          value indicates the default implementation.
 244:    * @param aLocation the location, from where the group implementation class
 245:    *          should be loaded (ignored for the system default implementation).
 246:    * @param aData the group intialization data
 247:    * @param aProperties the properties that will override the system properties
 248:    *          of the new group. These properties will be translated into -D
 249:    *          options.
 250:    * @param environment the record, containing path to the jre executable and
 251:    *          start options for the jre or null for using the default jre and
 252:    *          options.
 253:    */
 254:   public ActivationGroupDesc(String aClassName, String aLocation,
 255:                              MarshalledObject<?> aData, Properties aProperties,
 256:                              ActivationGroupDesc.CommandEnvironment environment)
 257:   {
 258:     className = aClassName;
 259:     location = aLocation;
 260:     data = aData;
 261:     props = aProperties;
 262:     env = environment;
 263:   }
 264: 
 265:   /**
 266:    * Get the activation group class name.
 267:    *
 268:    * @return the activation group class name (null for default implementation)
 269:    */
 270:   public String getClassName()
 271:   {
 272:     return className;
 273:   }
 274: 
 275:   /**
 276:    * Get the location, from where the group class will be loaded
 277:    *
 278:    * @return the location, from where the implementation should be loaded (null
 279:    *         for the default implementation)
 280:    */
 281:   public String getLocation()
 282:   {
 283:     return location;
 284:   }
 285: 
 286:   /**
 287:    * Get the group intialization data.
 288:    *
 289:    * @return the group intialization data in the marshalled form.
 290:    */
 291:   public MarshalledObject<?> getData()
 292:   {
 293:     return data;
 294:   }
 295: 
 296:   /**
 297:    * Get the overridded system properties.
 298:    *
 299:    * @return the overridden group system properties.
 300:    */
 301:   public Properties getPropertyOverrides()
 302:   {
 303:     return props;
 304:   }
 305: 
 306:   /**
 307:    * Get the group command environment, containing path to the jre executable
 308:    * and startup options.
 309:    *
 310:    * @return the command environment or null if the default environment should
 311:    *         be used.
 312:    */
 313:   public ActivationGroupDesc.CommandEnvironment getCommandEnvironment()
 314:   {
 315:     return env;
 316:   }
 317: 
 318:   /**
 319:    * Compare for the content equality.
 320:    */
 321:   public boolean equals(Object obj)
 322:   {
 323:     if (obj instanceof ActivationGroupDesc)
 324:       {
 325:         ActivationGroupDesc that = (ActivationGroupDesc) obj;
 326: 
 327:         // Ensure the hashcodes are computed.
 328:         if (hash == 0)
 329:           hashCode();
 330:         if (that.hash == 0)
 331:           that.hashCode();
 332: 
 333:         // We compare the hash fields as they are type long rather than int.
 334:         if (hash != that.hash)
 335:           return false;
 336: 
 337:         if (! eq(className, that.className))
 338:           return false;
 339:         if (! eq(data, that.data))
 340:           return false;
 341:         if (! eq(env, that.env))
 342:           return false;
 343:         if (! eq(location, that.location))
 344:           return false;
 345: 
 346:         // Compare the properties.
 347:         if (eq(props, that.props))
 348:           return true;
 349: 
 350:         if (props.size() != that.props.size())
 351:           return false;
 352: 
 353:         Enumeration en = props.propertyNames();
 354:         Object key, value;
 355: 
 356:         while (en.hasMoreElements())
 357:           {
 358:             key = en.nextElement();
 359:             if (! that.props.containsKey(key))
 360:               return false;
 361:             if (! eq(props.get(key), that.props.get(key)))
 362:               return false;
 363:           }
 364:         return true;
 365:       }
 366:     else
 367:       return false;
 368:   }
 369: 
 370:   /**
 371:    * Compare for direct equality if one or both parameters are null, otherwise
 372:    * call .equals.
 373:    */
 374:   static boolean eq(Object a, Object b)
 375:   {
 376:     if (a == null || b == null)
 377:       return a == b;
 378:     else
 379:       return a.equals(b);
 380:   }
 381: 
 382:   /**
 383:    * Return the hashcode.
 384:    */
 385:   public int hashCode()
 386:   {
 387:     if (hash==0)
 388:       {
 389:         // Using Adler32 - the hashcode is cached, will be computed only
 390:         // once and due need to scan properties is the expensive operation
 391:         // anyway. Reliability is more important.
 392:         Adler32 adler = new Adler32();
 393:         if (className!=null)
 394:           adler.update(className.getBytes());
 395:         if (data!=null)
 396:           adler.update(data.hashCode());
 397:         if (env!=null)
 398:           adler.update(env.hashCode());
 399:         if (location!=null)
 400:           adler.update(location.getBytes());
 401:         if (props!=null)
 402:           {
 403:             Enumeration en = props.propertyNames();
 404: 
 405:             // Using the intermediate sorted set to ensure that the
 406:             // properties are sorted.
 407:             TreeSet pr = new TreeSet();
 408: 
 409:             Object key;
 410:             Object value;
 411:             while (en.hasMoreElements())
 412:               {
 413:                 key = en.nextElement();
 414:                 if (key!=null)
 415:                   pr.add(key);
 416:               }
 417: 
 418:             Iterator it = pr.iterator();
 419:             while (it.hasNext())
 420:               {
 421:                 key = it.next();
 422:                 value = props.get(key);
 423:                 adler.update(key.hashCode());
 424:                 if (value!=null)
 425:                   adler.update(value.hashCode());
 426:               }
 427:           }
 428:           hash = adler.getValue();
 429:         }
 430:     return (int) hash;
 431:   }
 432: 
 433: }