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 */ CommandEnvironment(String commandPatch, String[] args)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 */ getCommandPath()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 */ getCommandOptions()137 public String[] getCommandOptions() 138 { 139 return options; 140 } 141 142 /** 143 * Compare for content equality. 144 */ equals(Object obj)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 */ hashCode()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 */ ActivationGroupDesc(Properties aProperties, ActivationGroupDesc.CommandEnvironment environment)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 */ ActivationGroupDesc(String aClassName, String aLocation, MarshalledObject<?> aData, Properties aProperties, ActivationGroupDesc.CommandEnvironment environment)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 */ getClassName()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 */ getLocation()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 */ getData()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 */ getPropertyOverrides()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 */ getCommandEnvironment()313 public ActivationGroupDesc.CommandEnvironment getCommandEnvironment() 314 { 315 return env; 316 } 317 318 /** 319 * Compare for the content equality. 320 */ equals(Object obj)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 */ eq(Object a, Object b)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 */ hashCode()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 } 434