/*
 * Copyright 2003-2004 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 com.sun.tools.jdi;

import java.io.IOException;
import java.util.Map;

import com.sun.jdi.Bootstrap;
import com.sun.jdi.VirtualMachine;
import com.sun.jdi.connect.*;
import com.sun.jdi.connect.spi.*;

/*
 * An AttachingConnector to attach to a running VM using any
 * TransportService.
 */

public class GenericAttachingConnector
        extends ConnectorImpl implements AttachingConnector
{
    /*
     * The arguments that this connector supports
     */
    static final String ARG_ADDRESS = "address";
    static final String ARG_TIMEOUT = "timeout";

    TransportService transportService;
    Transport transport;

    /*
     * Initialize a new instance of this connector. The connector
     * encapsulates a transport service and optionally has an
     * "address" connector argument.
     */
    private GenericAttachingConnector(TransportService ts,
                                      boolean addAddressArgument)
    {
        transportService = ts;
        transport = new Transport() {
                public String name() {
                    // delegate name to the transport service
                    return transportService.name();
                }
            };

        if (addAddressArgument) {
            addStringArgument(
                ARG_ADDRESS,
                getString("generic_attaching.address.label"),
                getString("generic_attaching.address"),
                "",
                true);
        }


        addIntegerArgument(
                ARG_TIMEOUT,
                getString("generic_attaching.timeout.label"),
                getString("generic_attaching.timeout"),
                "",
                false,
                0, Integer.MAX_VALUE);
    }

    /**
     * Initializes a new instance of this connector. This constructor
     * is used when sub-classing - the resulting connector will have
     * a "timeout" connector argument.
     */
    protected GenericAttachingConnector(TransportService ts) {
        this(ts, false);
    }

    /*
     * Create an instance of this connector. The resulting AttachingConnector
     * will have address and timeout connector arguments.
     */
    public static GenericAttachingConnector create(TransportService ts) {
        return new GenericAttachingConnector(ts, true);
    }

    /**
     * Attach to a target VM using the specified address and Connector arguments.
     */
    public VirtualMachine attach(String address, Map args)
        throws IOException, IllegalConnectorArgumentsException
    {
        String ts  = argument(ARG_TIMEOUT, args).value();
        int timeout = 0;
        if (ts.length() > 0) {
            timeout = Integer.decode(ts).intValue();
        }
        Connection connection = transportService.attach(address, timeout, 0);
        return Bootstrap.virtualMachineManager().createVirtualMachine(connection);
    }

    /**
     * Attach to a target VM using the specified arguments - the address
     * of the target VM is specified by the <code>address</code> connector
     * argument.
     */
    public VirtualMachine
        attach(Map<String,? extends Connector.Argument> args)
        throws IOException, IllegalConnectorArgumentsException
    {
        String address = argument(ARG_ADDRESS, args).value();
        return attach(address, args);
    }

    public String name() {
        return transport.name() + "Attach";
    }

    public String description() {
        return transportService.description();
    }

    public Transport transport() {
        return transport;
    }

}
