Frames | No Frames |
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: }