| /* ActivationGroupDesc.java -- the RMI activation group descriptor |
| Copyright (c) 1996, 1997, 1998, 1999, 2004, 2006 |
| Free Software Foundation, Inc. |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 02110-1301 USA. |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| |
| package java.rmi.activation; |
| |
| import gnu.java.rmi.activation.DefaultActivationGroup; |
| |
| import java.io.Serializable; |
| import java.rmi.MarshalledObject; |
| import java.util.Arrays; |
| import java.util.Enumeration; |
| import java.util.Iterator; |
| import java.util.Properties; |
| import java.util.TreeSet; |
| import java.util.zip.Adler32; |
| |
| /** |
| * Contains information, necessary to create of recreate the activation objects. |
| * The group descriptor contains: |
| * <ul> |
| * <li>The name of the group's class. This class is derived from the |
| * {@link ActivationGroup}.</li> |
| * <li>The group class code location.</li> |
| * <li>The marshalled object that contains the group specific initialization |
| * information</li> |
| * </ul> |
| * The groups are created by the {@link ActivationGroup#createGroup} method that |
| * expectes the group class to have the two parameter constructor, the first |
| * parameter being the {@link ActivationGroupID} and the second the |
| * {@link MarshalledObject}. |
| * |
| * @author Audrius Meskauskas (audriusa@bioinformatics.org) (from stub) |
| */ |
| public final class ActivationGroupDesc |
| implements Serializable |
| { |
| /** |
| * Contains the startup options for the {@link ActivationGroup} |
| * implementations. Allows to override system properties and specify other |
| * options for the implementation groups. |
| * |
| * @author Audrius Meskauskas (audriusa@bioinformatics.org) (from stub) |
| */ |
| public static class CommandEnvironment |
| implements Serializable |
| { |
| |
| /** |
| * Use the SVUID for interoperability. |
| */ |
| static final long serialVersionUID = 6165754737887770191L; |
| |
| /** |
| * The zero size string array used as argv value when null is passed. |
| */ |
| private static final String[] NO_ARGS = new String[0]; |
| |
| /** |
| * The path to the java executable (or null for using default jre). |
| */ |
| final String command; |
| |
| /** |
| * The extra parameters (may be empty array but never null). |
| */ |
| final String[] options; |
| |
| /** |
| * Create the new command environment. |
| * |
| * @param commandPatch the full path (and name) to the java executable of |
| * null for using the default executable. |
| * @param args extra options that will be used when creating the activation |
| * group. Null has the same effect as the empty list. |
| */ |
| public CommandEnvironment(String commandPatch, String[] args) |
| { |
| command = commandPatch; |
| if (args != null) |
| options = args; |
| else |
| options = NO_ARGS; |
| } |
| |
| /** |
| * Get the path to the java executable. |
| * |
| * @return the path to the java executable or null for using the default |
| * jre. |
| */ |
| public String getCommandPath() |
| { |
| return command; |
| } |
| |
| /** |
| * Get the additional command options. |
| * |
| * @return the command options array, may be empty string |
| */ |
| public String[] getCommandOptions() |
| { |
| return options; |
| } |
| |
| /** |
| * Compare for content equality. |
| */ |
| public boolean equals(Object obj) |
| { |
| if (obj instanceof CommandEnvironment) |
| { |
| CommandEnvironment that = (CommandEnvironment) obj; |
| |
| if (command == null || that.command == null) |
| { |
| // Use direct comparison if null is involved. |
| if (command != that.command) |
| return false; |
| } |
| else |
| { |
| // Use .equals if null is not involved. |
| if (! this.command.equals(that.command)) |
| return false; |
| } |
| |
| return Arrays.equals(options, that.options); |
| } |
| else |
| return false; |
| } |
| |
| /** |
| * Get the hash code. |
| */ |
| public int hashCode() |
| { |
| int h = command == null ? 0 : command.hashCode(); |
| for (int i = 0; i < options.length; i++) |
| h ^= options[i].hashCode(); |
| |
| return h; |
| } |
| } |
| |
| /** |
| * Use the SVUID for interoperability. |
| */ |
| static final long serialVersionUID = - 4936225423168276595L; |
| |
| /** |
| * The group class name or null for the default group class implementation. |
| */ |
| final String className; |
| |
| /** |
| * The group class download location URL (codebase), ignored by the |
| * default implementation. |
| */ |
| final String location; |
| |
| /** |
| * The group initialization data. |
| */ |
| final MarshalledObject data; |
| |
| /** |
| * The path to the group jre and the parameters of this jre, may be |
| * null for the default jre. |
| */ |
| final ActivationGroupDesc.CommandEnvironment env; |
| |
| /** |
| * The properties that override the system properties. |
| */ |
| final Properties props; |
| |
| /** |
| * The cached hash code. |
| */ |
| transient long hash; |
| |
| /** |
| * Create the new activation group descriptor that will use the default |
| * activation group implementation with the given properties and |
| * environment. |
| * |
| * @param aProperties the properties that override the system properties |
| * @param environment the command line (and parameters), indicating, where to |
| * find the jre executable and with that parameters to call it. May |
| * be null if the default executable should be used. In this case, |
| * the activation group with the null name (the system default group) |
| * will be created. |
| */ |
| public ActivationGroupDesc(Properties aProperties, |
| ActivationGroupDesc.CommandEnvironment environment) |
| { |
| this(DefaultActivationGroup.class.getName(), null, null, aProperties, |
| environment); |
| } |
| |
| /** |
| * Create the new activation group descriptor. |
| * |
| * @param aClassName the name of the group implementation class. The null |
| * value indicates the default implementation. |
| * @param aLocation the location, from where the group implementation class |
| * should be loaded (ignored for the system default implementation). |
| * @param aData the group intialization data |
| * @param aProperties the properties that will override the system properties |
| * of the new group. These properties will be translated into -D |
| * options. |
| * @param environment the record, containing path to the jre executable and |
| * start options for the jre or null for using the default jre and |
| * options. |
| */ |
| public ActivationGroupDesc(String aClassName, String aLocation, |
| MarshalledObject aData, Properties aProperties, |
| ActivationGroupDesc.CommandEnvironment environment) |
| { |
| className = aClassName; |
| location = aLocation; |
| data = aData; |
| props = aProperties; |
| env = environment; |
| } |
| |
| /** |
| * Get the activation group class name. |
| * |
| * @return the activation group class name (null for default implementation) |
| */ |
| public String getClassName() |
| { |
| return className; |
| } |
| |
| /** |
| * Get the location, from where the group class will be loaded |
| * |
| * @return the location, from where the implementation should be loaded (null |
| * for the default implementation) |
| */ |
| public String getLocation() |
| { |
| return location; |
| } |
| |
| /** |
| * Get the group intialization data. |
| * |
| * @return the group intialization data in the marshalled form. |
| */ |
| public MarshalledObject getData() |
| { |
| return data; |
| } |
| |
| /** |
| * Get the overridded system properties. |
| * |
| * @return the overridden group system properties. |
| */ |
| public Properties getPropertyOverrides() |
| { |
| return props; |
| } |
| |
| /** |
| * Get the group command environment, containing path to the jre executable |
| * and startup options. |
| * |
| * @return the command environment or null if the default environment should |
| * be used. |
| */ |
| public ActivationGroupDesc.CommandEnvironment getCommandEnvironment() |
| { |
| return env; |
| } |
| |
| /** |
| * Compare for the content equality. |
| */ |
| public boolean equals(Object obj) |
| { |
| if (obj instanceof ActivationGroupDesc) |
| { |
| ActivationGroupDesc that = (ActivationGroupDesc) obj; |
| |
| // Ensure the hashcodes are computed. |
| if (hash == 0) |
| hashCode(); |
| if (that.hash == 0) |
| that.hashCode(); |
| |
| // We compare the hash fields as they are type long rather than int. |
| if (hash != that.hash) |
| return false; |
| |
| if (! eq(className, that.className)) |
| return false; |
| if (! eq(data, that.data)) |
| return false; |
| if (! eq(env, that.env)) |
| return false; |
| if (! eq(location, that.location)) |
| return false; |
| |
| // Compare the properties. |
| if (eq(props, that.props)) |
| return true; |
| |
| if (props.size() != that.props.size()) |
| return false; |
| |
| Enumeration en = props.propertyNames(); |
| Object key, value; |
| |
| while (en.hasMoreElements()) |
| { |
| key = en.nextElement(); |
| if (! that.props.containsKey(key)) |
| return false; |
| if (! eq(props.get(key), that.props.get(key))) |
| return false; |
| } |
| return true; |
| } |
| else |
| return false; |
| } |
| |
| /** |
| * Compare for direct equality if one or both parameters are null, otherwise |
| * call .equals. |
| */ |
| static boolean eq(Object a, Object b) |
| { |
| if (a == null || b == null) |
| return a == b; |
| else |
| return a.equals(b); |
| } |
| |
| /** |
| * Return the hashcode. |
| */ |
| public int hashCode() |
| { |
| if (hash==0) |
| { |
| // Using Adler32 - the hashcode is cached, will be computed only |
| // once and due need to scan properties is the expensive operation |
| // anyway. Reliability is more important. |
| Adler32 adler = new Adler32(); |
| if (className!=null) |
| adler.update(className.getBytes()); |
| if (data!=null) |
| adler.update(data.hashCode()); |
| if (env!=null) |
| adler.update(env.hashCode()); |
| if (location!=null) |
| adler.update(location.getBytes()); |
| if (props!=null) |
| { |
| Enumeration en = props.propertyNames(); |
| |
| // Using the intermediate sorted set to ensure that the |
| // properties are sorted. |
| TreeSet pr = new TreeSet(); |
| |
| Object key; |
| Object value; |
| while (en.hasMoreElements()) |
| { |
| key = en.nextElement(); |
| if (key!=null) |
| pr.add(key); |
| } |
| |
| Iterator it = pr.iterator(); |
| while (it.hasNext()) |
| { |
| key = it.next(); |
| value = props.get(key); |
| adler.update(key.hashCode()); |
| if (value!=null) |
| adler.update(value.hashCode()); |
| } |
| } |
| hash = adler.getValue(); |
| } |
| return (int) hash; |
| } |
| |
| } |