/*
 * Copyright 1997-2005 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package java.rmi.activation;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.rmi.MarshalledObject;
import java.util.Arrays;
import java.util.Properties;

/**
 * An activation group descriptor contains the information necessary to
 * create/recreate an activation group in which to activate objects.
 * Such a descriptor contains: <ul>
 * <li> the group's class name,
 * <li> the group's code location (the location of the group's class), and
 * <li> a "marshalled" object that can contain group specific
 * initialization data. </ul> <p>
 *
 * The group's class must be a concrete subclass of
 * <code>ActivationGroup</code>. A subclass of
 * <code>ActivationGroup</code> is created/recreated via the
 * <code>ActivationGroup.createGroup</code> static method that invokes
 * a special constructor that takes two arguments: <ul>
 *
 * <li> the group's <code>ActivationGroupID</code>, and
 * <li> the group's initialization data (in a
 * <code>java.rmi.MarshalledObject</code>)</ul><p>
 *
 * @author      Ann Wollrath
 * @since       1.2
 * @see         ActivationGroup
 * @see         ActivationGroupID
 */
public final class ActivationGroupDesc implements Serializable {

    /**
     * @serial The group's fully package qualified class name.
     */
    private String className;

    /**
     * @serial The location from where to load the group's class.
     */
    private String location;

    /**
     * @serial The group's initialization data.
     */
    private MarshalledObject<?> data;

    /**
     * @serial The controlling options for executing the VM in
     * another process.
     */
    private CommandEnvironment env;

    /**
     * @serial A properties map which will override those set
     * by default in the subprocess environment.
     */
    private Properties props;

    /** indicate compatibility with the Java 2 SDK v1.2 version of class */
    private static final long serialVersionUID = -4936225423168276595L;

    /**
     * Constructs a group descriptor that uses the system defaults for group
     * implementation and code location.  Properties specify Java
     * environment overrides (which will override system properties in
     * the group implementation's VM).  The command
     * environment can control the exact command/options used in
     * starting the child VM, or can be <code>null</code> to accept
     * rmid's default.
     *
     * <p>This constructor will create an <code>ActivationGroupDesc</code>
     * with a <code>null</code> group class name, which indicates the system's
     * default <code>ActivationGroup</code> implementation.
     *
     * @param overrides the set of properties to set when the group is
     * recreated.
     * @param cmd the controlling options for executing the VM in
     * another process (or <code>null</code>).
     * @since 1.2
     */
    public ActivationGroupDesc(Properties overrides,
                               CommandEnvironment cmd)
    {
        this(null, null, null, overrides, cmd);
    }

    /**
     * Specifies an alternate group implementation and execution
     * environment to be used for the group.
     *
     * @param className the group's package qualified class name or
     * <code>null</code>. A <code>null</code> group class name indicates
     * the system's default <code>ActivationGroup</code> implementation.
     * @param location the location from where to load the group's
     * class
     * @param data the group's initialization data contained in
     * marshalled form (could contain properties, for example)
     * @param overrides a properties map which will override those set
     * by default in the subprocess environment (will be translated
     * into <code>-D</code> options), or <code>null</code>.
     * @param cmd the controlling options for executing the VM in
     * another process (or <code>null</code>).
     * @since 1.2
     */
    public ActivationGroupDesc(String className,
                               String location,
                               MarshalledObject<?> data,
                               Properties overrides,
                               CommandEnvironment cmd)
    {
        this.props = overrides;
        this.env = cmd;
        this.data = data;
        this.location = location;
        this.className = className;
    }

    /**
     * Returns the group's class name (possibly <code>null</code>).  A
     * <code>null</code> group class name indicates the system's default
     * <code>ActivationGroup</code> implementation.
     * @return the group's class name
     * @since 1.2
     */
    public String getClassName() {
        return className;
    }

    /**
     * Returns the group's code location.
     * @return the group's code location
     * @since 1.2
     */
    public String getLocation() {
        return location;
    }

    /**
     * Returns the group's initialization data.
     * @return the group's initialization data
     * @since 1.2
     */
    public MarshalledObject<?> getData() {
        return data;
    }

    /**
     * Returns the group's property-override list.
     * @return the property-override list, or <code>null</code>
     * @since 1.2
     */
    public Properties getPropertyOverrides() {
        return (props != null) ? (Properties) props.clone() : null;
    }

    /**
     * Returns the group's command-environment control object.
     * @return the command-environment object, or <code>null</code>
     * @since 1.2
     */
    public CommandEnvironment getCommandEnvironment() {
        return this.env;
    }


    /**
     * Startup options for ActivationGroup implementations.
     *
     * This class allows overriding default system properties and
     * specifying implementation-defined options for ActivationGroups.
     * @since 1.2
     */
    public static class CommandEnvironment implements Serializable {
        private static final long serialVersionUID = 6165754737887770191L;

        /**
         * @serial
         */
        private String command;

        /**
         * @serial
         */
        private String[] options;

        /**
         * Create a CommandEnvironment with all the necessary
         * information.
         *
         * @param cmdpath the name of the java executable, including
         * the full path, or <code>null</code>, meaning "use rmid's default".
         * The named program <em>must</em> be able to accept multiple
         * <code>-Dpropname=value</code> options (as documented for the
         * "java" tool)
         *
         * @param argv extra options which will be used in creating the
         * ActivationGroup.  Null has the same effect as an empty
         * list.
         * @since 1.2
         */
        public CommandEnvironment(String cmdpath,
                                  String[] argv)
        {
            this.command = cmdpath;     // might be null

            // Hold a safe copy of argv in this.options
            if (argv == null) {
                this.options = new String[0];
            } else {
                this.options = new String[argv.length];
                System.arraycopy(argv, 0, this.options, 0, argv.length);
            }
        }

        /**
         * Fetch the configured path-qualified java command name.
         *
         * @return the configured name, or <code>null</code> if configured to
         * accept the default
         * @since 1.2
         */
        public String getCommandPath() {
            return (this.command);
        }

        /**
         * Fetch the configured java command options.
         *
         * @return An array of the command options which will be passed
         * to the new child command by rmid.
         * Note that rmid may add other options before or after these
         * options, or both.
         * Never returns <code>null</code>.
         * @since 1.2
         */
        public String[] getCommandOptions() {
            return (String[]) options.clone();
        }

        /**
         * Compares two command environments for content equality.
         *
         * @param       obj     the Object to compare with
         * @return      true if these Objects are equal; false otherwise.
         * @see         java.util.Hashtable
         * @since 1.2
         */
        public boolean equals(Object obj) {

            if (obj instanceof CommandEnvironment) {
                CommandEnvironment env = (CommandEnvironment) obj;
                return
                    ((command == null ? env.command == null :
                      command.equals(env.command)) &&
                     Arrays.equals(options, env.options));
            } else {
                return false;
            }
        }

        /**
         * Return identical values for similar
         * <code>CommandEnvironment</code>s.
         * @return an integer
         * @see java.util.Hashtable
         */
        public int hashCode()
        {
            // hash command and ignore possibly expensive options
            return (command == null ? 0 : command.hashCode());
        }

        /**
         * <code>readObject</code> for custom serialization.
         *
         * <p>This method reads this object's serialized form for this
         * class as follows:
         *
         * <p>This method first invokes <code>defaultReadObject</code> on
         * the specified object input stream, and if <code>options</code>
         * is <code>null</code>, then <code>options</code> is set to a
         * zero-length array of <code>String</code>.
         */
        private void readObject(ObjectInputStream in)
            throws IOException, ClassNotFoundException
        {
            in.defaultReadObject();
            if (options == null) {
                options = new String[0];
            }
        }
    }

    /**
     * Compares two activation group descriptors for content equality.
     *
     * @param   obj     the Object to compare with
     * @return  true if these Objects are equal; false otherwise.
     * @see             java.util.Hashtable
     * @since 1.2
     */
    public boolean equals(Object obj) {

        if (obj instanceof ActivationGroupDesc) {
            ActivationGroupDesc desc = (ActivationGroupDesc) obj;
            return
                ((className == null ? desc.className == null :
                  className.equals(desc.className)) &&
                 (location == null ? desc.location == null :
                  location.equals(desc.location)) &&
                 (data == null ? desc.data == null : data.equals(desc.data)) &&
                 (env == null ? desc.env == null : env.equals(desc.env)) &&
                 (props == null ? desc.props == null :
                  props.equals(desc.props)));
        } else {
            return false;
        }
    }

    /**
     * Produce identical numbers for similar <code>ActivationGroupDesc</code>s.
     * @return an integer
     * @see java.util.Hashtable
     */
    public int hashCode() {
        // hash location, className, data, and env
        // but omit props (may be expensive)
        return ((location == null
                    ? 0
                    : location.hashCode() << 24) ^
                (env == null
                    ? 0
                    : env.hashCode() << 16) ^
                (className == null
                    ? 0
                    : className.hashCode() << 8) ^
                (data == null
                    ? 0
                    : data.hashCode()));
    }
}
