1 /* 2 * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.rmi.activation; 27 28 import java.io.IOException; 29 import java.io.ObjectInputStream; 30 import java.io.Serializable; 31 import java.rmi.MarshalledObject; 32 import java.util.Arrays; 33 import java.util.Properties; 34 35 /** 36 * An activation group descriptor contains the information necessary to 37 * create/recreate an activation group in which to activate objects. 38 * Such a descriptor contains: <ul> 39 * <li> the group's class name, 40 * <li> the group's code location (the location of the group's class), and 41 * <li> a "marshalled" object that can contain group specific 42 * initialization data. </ul> <p> 43 * 44 * The group's class must be a concrete subclass of 45 * <code>ActivationGroup</code>. A subclass of 46 * <code>ActivationGroup</code> is created/recreated via the 47 * <code>ActivationGroup.createGroup</code> static method that invokes 48 * a special constructor that takes two arguments: <ul> 49 * 50 * <li> the group's <code>ActivationGroupID</code>, and 51 * <li> the group's initialization data (in a 52 * <code>java.rmi.MarshalledObject</code>)</ul> 53 * 54 * @author Ann Wollrath 55 * @since 1.2 56 * @see ActivationGroup 57 * @see ActivationGroupID 58 */ 59 public final class ActivationGroupDesc implements Serializable { 60 61 /** 62 * @serial The group's fully package qualified class name. 63 */ 64 private String className; 65 66 /** 67 * @serial The location from where to load the group's class. 68 */ 69 private String location; 70 71 /** 72 * @serial The group's initialization data. 73 */ 74 private MarshalledObject<?> data; 75 76 /** 77 * @serial The controlling options for executing the VM in 78 * another process. 79 */ 80 private CommandEnvironment env; 81 82 /** 83 * @serial A properties map which will override those set 84 * by default in the subprocess environment. 85 */ 86 private Properties props; 87 88 /** indicate compatibility with the Java 2 SDK v1.2 version of class */ 89 private static final long serialVersionUID = -4936225423168276595L; 90 91 /** 92 * Constructs a group descriptor that uses the system defaults for group 93 * implementation and code location. Properties specify Java 94 * environment overrides (which will override system properties in 95 * the group implementation's VM). The command 96 * environment can control the exact command/options used in 97 * starting the child VM, or can be <code>null</code> to accept 98 * rmid's default. 99 * 100 * <p>This constructor will create an <code>ActivationGroupDesc</code> 101 * with a <code>null</code> group class name, which indicates the system's 102 * default <code>ActivationGroup</code> implementation. 103 * 104 * @param overrides the set of properties to set when the group is 105 * recreated. 106 * @param cmd the controlling options for executing the VM in 107 * another process (or <code>null</code>). 108 * @since 1.2 109 */ 110 public ActivationGroupDesc(Properties overrides, 111 CommandEnvironment cmd) 112 { 113 this(null, null, null, overrides, cmd); 114 } 115 116 /** 117 * Specifies an alternate group implementation and execution 118 * environment to be used for the group. 119 * 120 * @param className the group's package qualified class name or 121 * <code>null</code>. A <code>null</code> group class name indicates 122 * the system's default <code>ActivationGroup</code> implementation. 123 * @param location the location from where to load the group's 124 * class 125 * @param data the group's initialization data contained in 126 * marshalled form (could contain properties, for example) 127 * @param overrides a properties map which will override those set 128 * by default in the subprocess environment (will be translated 129 * into <code>-D</code> options), or <code>null</code>. 130 * @param cmd the controlling options for executing the VM in 131 * another process (or <code>null</code>). 132 * @since 1.2 133 */ 134 public ActivationGroupDesc(String className, 135 String location, 136 MarshalledObject<?> data, 137 Properties overrides, 138 CommandEnvironment cmd) 139 { 140 this.props = overrides; 141 this.env = cmd; 142 this.data = data; 143 this.location = location; 144 this.className = className; 145 } 146 147 /** 148 * Returns the group's class name (possibly <code>null</code>). A 149 * <code>null</code> group class name indicates the system's default 150 * <code>ActivationGroup</code> implementation. 151 * @return the group's class name 152 * @since 1.2 153 */ 154 public String getClassName() { 155 return className; 156 } 157 158 /** 159 * Returns the group's code location. 160 * @return the group's code location 161 * @since 1.2 162 */ 163 public String getLocation() { 164 return location; 165 } 166 167 /** 168 * Returns the group's initialization data. 169 * @return the group's initialization data 170 * @since 1.2 171 */ 172 public MarshalledObject<?> getData() { 173 return data; 174 } 175 176 /** 177 * Returns the group's property-override list. 178 * @return the property-override list, or <code>null</code> 179 * @since 1.2 180 */ 181 public Properties getPropertyOverrides() { 182 return (props != null) ? (Properties) props.clone() : null; 183 } 184 185 /** 186 * Returns the group's command-environment control object. 187 * @return the command-environment object, or <code>null</code> 188 * @since 1.2 189 */ 190 public CommandEnvironment getCommandEnvironment() { 191 return this.env; 192 } 193 194 195 /** 196 * Startup options for ActivationGroup implementations. 197 * 198 * This class allows overriding default system properties and 199 * specifying implementation-defined options for ActivationGroups. 200 * @since 1.2 201 */ 202 public static class CommandEnvironment implements Serializable { 203 private static final long serialVersionUID = 6165754737887770191L; 204 205 /** 206 * @serial 207 */ 208 private String command; 209 210 /** 211 * @serial 212 */ 213 private String[] options; 214 215 /** 216 * Create a CommandEnvironment with all the necessary 217 * information. 218 * 219 * @param cmdpath the name of the java executable, including 220 * the full path, or <code>null</code>, meaning "use rmid's default". 221 * The named program <em>must</em> be able to accept multiple 222 * <code>-Dpropname=value</code> options (as documented for the 223 * "java" tool) 224 * 225 * @param argv extra options which will be used in creating the 226 * ActivationGroup. Null has the same effect as an empty 227 * list. 228 * @since 1.2 229 */ 230 public CommandEnvironment(String cmdpath, 231 String[] argv) 232 { 233 this.command = cmdpath; // might be null 234 235 // Hold a safe copy of argv in this.options 236 if (argv == null) { 237 this.options = new String[0]; 238 } else { 239 this.options = new String[argv.length]; 240 System.arraycopy(argv, 0, this.options, 0, argv.length); 241 } 242 } 243 244 /** 245 * Fetch the configured path-qualified java command name. 246 * 247 * @return the configured name, or <code>null</code> if configured to 248 * accept the default 249 * @since 1.2 250 */ 251 public String getCommandPath() { 252 return (this.command); 253 } 254 255 /** 256 * Fetch the configured java command options. 257 * 258 * @return An array of the command options which will be passed 259 * to the new child command by rmid. 260 * Note that rmid may add other options before or after these 261 * options, or both. 262 * Never returns <code>null</code>. 263 * @since 1.2 264 */ 265 public String[] getCommandOptions() { 266 return options.clone(); 267 } 268 269 /** 270 * Compares two command environments for content equality. 271 * 272 * @param obj the Object to compare with 273 * @return true if these Objects are equal; false otherwise. 274 * @see java.util.Hashtable 275 * @since 1.2 276 */ 277 public boolean equals(Object obj) { 278 279 if (obj instanceof CommandEnvironment) { 280 CommandEnvironment env = (CommandEnvironment) obj; 281 return 282 ((command == null ? env.command == null : 283 command.equals(env.command)) && 284 Arrays.equals(options, env.options)); 285 } else { 286 return false; 287 } 288 } 289 290 /** 291 * Return identical values for similar 292 * <code>CommandEnvironment</code>s. 293 * @return an integer 294 * @see java.util.Hashtable 295 */ 296 public int hashCode() 297 { 298 // hash command and ignore possibly expensive options 299 return (command == null ? 0 : command.hashCode()); 300 } 301 302 /** 303 * <code>readObject</code> for custom serialization. 304 * 305 * <p>This method reads this object's serialized form for this 306 * class as follows: 307 * 308 * <p>This method first invokes <code>defaultReadObject</code> on 309 * the specified object input stream, and if <code>options</code> 310 * is <code>null</code>, then <code>options</code> is set to a 311 * zero-length array of <code>String</code>. 312 */ 313 private void readObject(ObjectInputStream in) 314 throws IOException, ClassNotFoundException 315 { 316 in.defaultReadObject(); 317 if (options == null) { 318 options = new String[0]; 319 } 320 } 321 } 322 323 /** 324 * Compares two activation group descriptors for content equality. 325 * 326 * @param obj the Object to compare with 327 * @return true if these Objects are equal; false otherwise. 328 * @see java.util.Hashtable 329 * @since 1.2 330 */ 331 public boolean equals(Object obj) { 332 333 if (obj instanceof ActivationGroupDesc) { 334 ActivationGroupDesc desc = (ActivationGroupDesc) obj; 335 return 336 ((className == null ? desc.className == null : 337 className.equals(desc.className)) && 338 (location == null ? desc.location == null : 339 location.equals(desc.location)) && 340 (data == null ? desc.data == null : data.equals(desc.data)) && 341 (env == null ? desc.env == null : env.equals(desc.env)) && 342 (props == null ? desc.props == null : 343 props.equals(desc.props))); 344 } else { 345 return false; 346 } 347 } 348 349 /** 350 * Produce identical numbers for similar <code>ActivationGroupDesc</code>s. 351 * @return an integer 352 * @see java.util.Hashtable 353 */ 354 public int hashCode() { 355 // hash location, className, data, and env 356 // but omit props (may be expensive) 357 return ((location == null 358 ? 0 359 : location.hashCode() << 24) ^ 360 (env == null 361 ? 0 362 : env.hashCode() << 16) ^ 363 (className == null 364 ? 0 365 : className.hashCode() << 8) ^ 366 (data == null 367 ? 0 368 : data.hashCode())); 369 } 370 }