/*
 * Copyright 2003-2006 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 sun.management.snmp;

import com.sun.jmx.snmp.daemon.SnmpAdaptorServer;
import com.sun.jmx.snmp.InetAddressAcl;
import com.sun.jmx.snmp.IPAcl.SnmpAcl;
import sun.management.snmp.jvmmib.JVM_MANAGEMENT_MIB;
import sun.management.snmp.jvminstr.JVM_MANAGEMENT_MIB_IMPL;
import sun.management.snmp.jvminstr.NotificationTarget;
import sun.management.snmp.jvminstr.NotificationTargetImpl;
import sun.management.snmp.util.MibLogger;
import sun.management.snmp.util.JvmContextFactory;

import sun.management.Agent;
import sun.management.AgentConfigurationError;
import static sun.management.AgentConfigurationError.*;
import sun.management.FileSystem;

import java.util.List;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Properties;

import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * This class initializes and starts the SNMP Adaptor for JSR 163 SNMP
 * Monitoring.
 **/
public final class AdaptorBootstrap {

    private static final MibLogger log = new MibLogger(AdaptorBootstrap.class);

    /**
     * Default values for SNMP configuration properties.
     **/
    public static interface DefaultValues {
        public static final String PORT="161";
        public static final String CONFIG_FILE_NAME="management.properties";
        public static final String TRAP_PORT="162";
        public static final String USE_ACL="true";
        public static final String ACL_FILE_NAME="snmp.acl";
        public static final String BIND_ADDRESS="localhost";
    }

    /**
     * Names of SNMP configuration properties.
     **/
    public static interface PropertyNames {
        public static final String PORT="com.sun.management.snmp.port";
        public static final String CONFIG_FILE_NAME=
            "com.sun.management.config.file";
        public static final String TRAP_PORT=
            "com.sun.management.snmp.trap";
        public static final String USE_ACL=
            "com.sun.management.snmp.acl";
        public static final String ACL_FILE_NAME=
            "com.sun.management.snmp.acl.file";
        public static final String BIND_ADDRESS=
            "com.sun.management.snmp.interface";
    }

    /**
     * We keep a reference - so that we can possibly call
     * terminate(). As of now, terminate() is only called by unit tests
     * (makes it possible to run several testcases sequentially in the
     * same JVM).
     **/
    private SnmpAdaptorServer       adaptor;
    private JVM_MANAGEMENT_MIB_IMPL jvmmib;

    private AdaptorBootstrap(SnmpAdaptorServer snmpas,
                             JVM_MANAGEMENT_MIB_IMPL mib) {
        jvmmib  = mib;
        adaptor = snmpas;
    }

    /**
     * Compute the full path name for a default file.
     * @param basename basename (with extension) of the default file.
     * @return ${JRE}/lib/management/${basename}
     **/
    private static String getDefaultFileName(String basename) {
        final String fileSeparator = File.separator;
        return System.getProperty("java.home") + fileSeparator + "lib" +
            fileSeparator + "management" + fileSeparator + basename;
    }

    /**
     * Retrieve the Trap Target List from the ACL file.
     **/
    private static List<NotificationTarget> getTargetList(InetAddressAcl acl,
                                                          int defaultTrapPort) {
        final ArrayList<NotificationTarget> result =
                new ArrayList<NotificationTarget>();
        if (acl != null) {
            if (log.isDebugOn())
                log.debug("getTargetList",Agent.getText("jmxremote.AdaptorBootstrap.getTargetList.processing"));

            final Enumeration td=acl.getTrapDestinations();
            for (; td.hasMoreElements() ;) {
                final InetAddress targetAddr = (InetAddress)td.nextElement();
                final Enumeration tc =
                    acl.getTrapCommunities(targetAddr);
                for (;tc.hasMoreElements() ;) {
                    final String community = (String) tc.nextElement();
                    final NotificationTarget target =
                        new NotificationTargetImpl(targetAddr,
                                                   defaultTrapPort,
                                                   community);
                    if (log.isDebugOn())
                        log.debug("getTargetList",
                                  Agent.getText("jmxremote.AdaptorBootstrap.getTargetList.adding",
                                                target.toString()));
                    result.add(target);
                }
            }
        }
        return result;
    }

    /**
     * Initializes and starts the SNMP Adaptor Server.
     * If the com.sun.management.snmp.port property is not defined,
     * simply return. Otherwise, attempts to load the config file, and
     * then calls {@link #initialize(java.lang.String, java.util.Properties)}.
     *
     **/
    public static synchronized AdaptorBootstrap initialize() {

        // Load a new properties
        final Properties props = Agent.loadManagementProperties();
        if (props == null) return null;

        final String portStr = props.getProperty(PropertyNames.PORT);

        return initialize(portStr,props);
    }

    /**
     * Initializes and starts the SNMP Adaptor Server.
     **/
    public static synchronized
        AdaptorBootstrap initialize(String portStr, Properties props) {

        // Get port number
        if (portStr.length()==0) portStr=DefaultValues.PORT;
        final int port;
        try {
            port = Integer.parseInt(portStr);
        } catch (NumberFormatException x) {
            throw new AgentConfigurationError(INVALID_SNMP_PORT, x, portStr);
        }

        if (port < 0) {
            throw new AgentConfigurationError(INVALID_SNMP_PORT, portStr);
        }

        // Get trap port number
        final String trapPortStr =
            props.getProperty(PropertyNames.TRAP_PORT,
                              DefaultValues.TRAP_PORT);

        final int trapPort;
        try {
            trapPort = Integer.parseInt(trapPortStr);
        } catch (NumberFormatException x) {
            throw new AgentConfigurationError(INVALID_SNMP_TRAP_PORT, x, trapPortStr);
        }

        if (trapPort < 0) {
            throw new AgentConfigurationError(INVALID_SNMP_TRAP_PORT, trapPortStr);
        }

        // Get bind address
        final String addrStr =
            props.getProperty(PropertyNames.BIND_ADDRESS,
                              DefaultValues.BIND_ADDRESS);

        // Get ACL File
        final String defaultAclFileName   =
            getDefaultFileName(DefaultValues.ACL_FILE_NAME);
        final String aclFileName =
            props.getProperty(PropertyNames.ACL_FILE_NAME,
                               defaultAclFileName);
        final String  useAclStr =
            props.getProperty(PropertyNames.USE_ACL,DefaultValues.USE_ACL);
        final boolean useAcl =
            Boolean.valueOf(useAclStr).booleanValue();

        if (useAcl) checkAclFile(aclFileName);

        AdaptorBootstrap adaptor = null;
        try {
            adaptor = getAdaptorBootstrap(port, trapPort, addrStr,
                                          useAcl, aclFileName);
        } catch (Exception e) {
            throw new AgentConfigurationError(AGENT_EXCEPTION, e, e.getMessage());
        }
        return adaptor;
    }

    private static AdaptorBootstrap getAdaptorBootstrap
        (int port, int trapPort, String bindAddress, boolean useAcl,
         String aclFileName) {

        final InetAddress address;
        try {
            address = InetAddress.getByName(bindAddress);
        } catch (UnknownHostException e) {
            throw new AgentConfigurationError(UNKNOWN_SNMP_INTERFACE, e, bindAddress);
        }
        if (log.isDebugOn()) {
            log.debug("initialize",
                      Agent.getText("jmxremote.AdaptorBootstrap.getTargetList.starting" +
                      "\n\t" + PropertyNames.PORT + "=" + port +
                      "\n\t" + PropertyNames.TRAP_PORT + "=" + trapPort +
                      "\n\t" + PropertyNames.BIND_ADDRESS + "=" + address +
                      (useAcl?("\n\t" + PropertyNames.ACL_FILE_NAME + "="
                               + aclFileName):"\n\tNo ACL")+
                      ""));
        }

        final InetAddressAcl acl;
        try {
            acl = useAcl ? new SnmpAcl(System.getProperty("user.name"),aclFileName)
                         : null;
        } catch (UnknownHostException e) {
            throw new AgentConfigurationError(UNKNOWN_SNMP_INTERFACE, e, e.getMessage());
        }

        // Create adaptor
        final SnmpAdaptorServer adaptor =
            new SnmpAdaptorServer(acl, port, address);
        adaptor.setUserDataFactory(new JvmContextFactory());
        adaptor.setTrapPort(trapPort);

        // Create MIB
        //
        final JVM_MANAGEMENT_MIB_IMPL mib = new JVM_MANAGEMENT_MIB_IMPL();
        try {
            mib.init();
        } catch (IllegalAccessException x) {
            throw new AgentConfigurationError(SNMP_MIB_INIT_FAILED, x, x.getMessage());
        }

        // Configure the trap destinations.
        //
        mib.addTargets(getTargetList(acl,trapPort));


        // Start Adaptor
        //
        try {
            // Will wait until the adaptor starts or fails to start.
            // If the adaptor fails to start, a CommunicationException or
            // an InterruptedException is thrown.
            //
            adaptor.start(Long.MAX_VALUE);
        } catch (Exception x) {
            Throwable t=x;
            if (x instanceof com.sun.jmx.snmp.daemon.CommunicationException) {
                final Throwable next = t.getCause();
                if (next != null) t = next;
            }
            throw new AgentConfigurationError(SNMP_ADAPTOR_START_FAILED, t,
                                              address + ":" + port,
                                              "(" + t.getMessage() + ")");
        }

        // double check that adaptor is actually started (should always
        // be active, so that exception should never be thrown from here)
        //
        if (!adaptor.isActive()) {
            throw new AgentConfigurationError(SNMP_ADAPTOR_START_FAILED,
                                              address + ":" + port);
        }

        try {
            // Add MIB to adaptor
            //
            adaptor.addMib(mib);

            // Add Adaptor to the MIB
            //
            mib.setSnmpAdaptor(adaptor);
        } catch (RuntimeException x) {
            new AdaptorBootstrap(adaptor,mib).terminate();
            throw x;
        }

        log.debug("initialize",
                  Agent.getText("jmxremote.AdaptorBootstrap.getTargetList.initialize1"));
        log.config("initialize",
                   Agent.getText("jmxremote.AdaptorBootstrap.getTargetList.initialize2",
                                 address.toString(), java.lang.Integer.toString(adaptor.getPort())));
        return new AdaptorBootstrap(adaptor,mib);
    }

    private static void checkAclFile(String aclFileName) {
        if (aclFileName == null || aclFileName.length()==0) {
            throw new AgentConfigurationError(SNMP_ACL_FILE_NOT_SET);
        }
        final File file = new File(aclFileName);
        if (!file.exists()) {
            throw new AgentConfigurationError(SNMP_ACL_FILE_NOT_FOUND, aclFileName);
        }
        if (!file.canRead()) {
            throw new AgentConfigurationError(SNMP_ACL_FILE_NOT_READABLE, aclFileName);
        }

        FileSystem fs = FileSystem.open();
        try {
            if (fs.supportsFileSecurity(file)) {
                if (!fs.isAccessUserOnly(file)) {
                    throw new AgentConfigurationError(SNMP_ACL_FILE_ACCESS_NOT_RESTRICTED,
                        aclFileName);
                }
            }
        } catch (IOException e) {
            throw new AgentConfigurationError(SNMP_ACL_FILE_READ_FAILED, aclFileName);

        }
    }


    /**
     * Get the port on which the adaptor is bound.
     * Returns 0 if the adaptor is already terminated.
     *
     **/
    public synchronized int getPort() {
        if (adaptor != null) return adaptor.getPort();
        return 0;
    }

    /**
     * Stops the adaptor server.
     **/
    public synchronized void terminate() {
        if (adaptor == null) return;

        // Terminate the MIB (deregister NotificationListener from
        // MemoryMBean)
        //
        try {
            jvmmib.terminate();
        } catch (Exception x) {
            // Must not prevent to stop...
            //
            log.debug("jmxremote.AdaptorBootstrap.getTargetList.terminate",
                      x.toString());
        } finally {
            jvmmib=null;
        }

        // Stop the adaptor
        //
        try {
            adaptor.stop();
        } finally {
            adaptor = null;
        }
    }

}
