0N/A/*
2362N/A * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.management.snmp;
0N/A
0N/Aimport com.sun.jmx.snmp.daemon.SnmpAdaptorServer;
0N/Aimport com.sun.jmx.snmp.InetAddressAcl;
0N/Aimport com.sun.jmx.snmp.IPAcl.SnmpAcl;
0N/Aimport sun.management.snmp.jvmmib.JVM_MANAGEMENT_MIB;
0N/Aimport sun.management.snmp.jvminstr.JVM_MANAGEMENT_MIB_IMPL;
0N/Aimport sun.management.snmp.jvminstr.NotificationTarget;
0N/Aimport sun.management.snmp.jvminstr.NotificationTargetImpl;
0N/Aimport sun.management.snmp.util.MibLogger;
0N/Aimport sun.management.snmp.util.JvmContextFactory;
0N/A
0N/Aimport sun.management.Agent;
0N/Aimport sun.management.AgentConfigurationError;
0N/Aimport static sun.management.AgentConfigurationError.*;
0N/Aimport sun.management.FileSystem;
0N/A
0N/Aimport java.util.List;
0N/Aimport java.util.ArrayList;
0N/Aimport java.util.Enumeration;
0N/Aimport java.util.Properties;
0N/A
0N/Aimport java.io.IOException;
0N/Aimport java.io.File;
0N/Aimport java.io.FileInputStream;
0N/A
0N/Aimport java.net.InetAddress;
0N/Aimport java.net.UnknownHostException;
0N/A
0N/A/**
0N/A * This class initializes and starts the SNMP Adaptor for JSR 163 SNMP
0N/A * Monitoring.
0N/A **/
0N/Apublic final class AdaptorBootstrap {
0N/A
0N/A private static final MibLogger log = new MibLogger(AdaptorBootstrap.class);
0N/A
0N/A /**
0N/A * Default values for SNMP configuration properties.
0N/A **/
0N/A public static interface DefaultValues {
0N/A public static final String PORT="161";
0N/A public static final String CONFIG_FILE_NAME="management.properties";
0N/A public static final String TRAP_PORT="162";
0N/A public static final String USE_ACL="true";
0N/A public static final String ACL_FILE_NAME="snmp.acl";
0N/A public static final String BIND_ADDRESS="localhost";
0N/A }
0N/A
0N/A /**
0N/A * Names of SNMP configuration properties.
0N/A **/
0N/A public static interface PropertyNames {
0N/A public static final String PORT="com.sun.management.snmp.port";
0N/A public static final String CONFIG_FILE_NAME=
0N/A "com.sun.management.config.file";
0N/A public static final String TRAP_PORT=
0N/A "com.sun.management.snmp.trap";
0N/A public static final String USE_ACL=
0N/A "com.sun.management.snmp.acl";
0N/A public static final String ACL_FILE_NAME=
0N/A "com.sun.management.snmp.acl.file";
0N/A public static final String BIND_ADDRESS=
0N/A "com.sun.management.snmp.interface";
0N/A }
0N/A
0N/A /**
0N/A * We keep a reference - so that we can possibly call
0N/A * terminate(). As of now, terminate() is only called by unit tests
0N/A * (makes it possible to run several testcases sequentially in the
0N/A * same JVM).
0N/A **/
0N/A private SnmpAdaptorServer adaptor;
0N/A private JVM_MANAGEMENT_MIB_IMPL jvmmib;
0N/A
0N/A private AdaptorBootstrap(SnmpAdaptorServer snmpas,
0N/A JVM_MANAGEMENT_MIB_IMPL mib) {
0N/A jvmmib = mib;
0N/A adaptor = snmpas;
0N/A }
0N/A
0N/A /**
0N/A * Compute the full path name for a default file.
0N/A * @param basename basename (with extension) of the default file.
0N/A * @return ${JRE}/lib/management/${basename}
0N/A **/
0N/A private static String getDefaultFileName(String basename) {
0N/A final String fileSeparator = File.separator;
0N/A return System.getProperty("java.home") + fileSeparator + "lib" +
0N/A fileSeparator + "management" + fileSeparator + basename;
0N/A }
0N/A
0N/A /**
0N/A * Retrieve the Trap Target List from the ACL file.
0N/A **/
0N/A private static List<NotificationTarget> getTargetList(InetAddressAcl acl,
0N/A int defaultTrapPort) {
0N/A final ArrayList<NotificationTarget> result =
0N/A new ArrayList<NotificationTarget>();
0N/A if (acl != null) {
0N/A if (log.isDebugOn())
0N/A log.debug("getTargetList",Agent.getText("jmxremote.AdaptorBootstrap.getTargetList.processing"));
0N/A
0N/A final Enumeration td=acl.getTrapDestinations();
0N/A for (; td.hasMoreElements() ;) {
0N/A final InetAddress targetAddr = (InetAddress)td.nextElement();
0N/A final Enumeration tc =
0N/A acl.getTrapCommunities(targetAddr);
0N/A for (;tc.hasMoreElements() ;) {
0N/A final String community = (String) tc.nextElement();
0N/A final NotificationTarget target =
0N/A new NotificationTargetImpl(targetAddr,
0N/A defaultTrapPort,
0N/A community);
0N/A if (log.isDebugOn())
0N/A log.debug("getTargetList",
0N/A Agent.getText("jmxremote.AdaptorBootstrap.getTargetList.adding",
0N/A target.toString()));
0N/A result.add(target);
0N/A }
0N/A }
0N/A }
0N/A return result;
0N/A }
0N/A
0N/A /**
0N/A * Initializes and starts the SNMP Adaptor Server.
0N/A * If the com.sun.management.snmp.port property is not defined,
0N/A * simply return. Otherwise, attempts to load the config file, and
0N/A * then calls {@link #initialize(java.lang.String, java.util.Properties)}.
0N/A *
0N/A **/
0N/A public static synchronized AdaptorBootstrap initialize() {
0N/A
0N/A // Load a new properties
0N/A final Properties props = Agent.loadManagementProperties();
0N/A if (props == null) return null;
0N/A
0N/A final String portStr = props.getProperty(PropertyNames.PORT);
0N/A
0N/A return initialize(portStr,props);
0N/A }
0N/A
0N/A /**
0N/A * Initializes and starts the SNMP Adaptor Server.
0N/A **/
0N/A public static synchronized
0N/A AdaptorBootstrap initialize(String portStr, Properties props) {
0N/A
0N/A // Get port number
0N/A if (portStr.length()==0) portStr=DefaultValues.PORT;
0N/A final int port;
0N/A try {
0N/A port = Integer.parseInt(portStr);
0N/A } catch (NumberFormatException x) {
0N/A throw new AgentConfigurationError(INVALID_SNMP_PORT, x, portStr);
0N/A }
0N/A
0N/A if (port < 0) {
0N/A throw new AgentConfigurationError(INVALID_SNMP_PORT, portStr);
0N/A }
0N/A
0N/A // Get trap port number
0N/A final String trapPortStr =
0N/A props.getProperty(PropertyNames.TRAP_PORT,
0N/A DefaultValues.TRAP_PORT);
0N/A
0N/A final int trapPort;
0N/A try {
0N/A trapPort = Integer.parseInt(trapPortStr);
0N/A } catch (NumberFormatException x) {
0N/A throw new AgentConfigurationError(INVALID_SNMP_TRAP_PORT, x, trapPortStr);
0N/A }
0N/A
0N/A if (trapPort < 0) {
0N/A throw new AgentConfigurationError(INVALID_SNMP_TRAP_PORT, trapPortStr);
0N/A }
0N/A
0N/A // Get bind address
0N/A final String addrStr =
0N/A props.getProperty(PropertyNames.BIND_ADDRESS,
0N/A DefaultValues.BIND_ADDRESS);
0N/A
0N/A // Get ACL File
0N/A final String defaultAclFileName =
0N/A getDefaultFileName(DefaultValues.ACL_FILE_NAME);
0N/A final String aclFileName =
0N/A props.getProperty(PropertyNames.ACL_FILE_NAME,
0N/A defaultAclFileName);
0N/A final String useAclStr =
0N/A props.getProperty(PropertyNames.USE_ACL,DefaultValues.USE_ACL);
0N/A final boolean useAcl =
0N/A Boolean.valueOf(useAclStr).booleanValue();
0N/A
0N/A if (useAcl) checkAclFile(aclFileName);
0N/A
0N/A AdaptorBootstrap adaptor = null;
0N/A try {
0N/A adaptor = getAdaptorBootstrap(port, trapPort, addrStr,
0N/A useAcl, aclFileName);
0N/A } catch (Exception e) {
0N/A throw new AgentConfigurationError(AGENT_EXCEPTION, e, e.getMessage());
0N/A }
0N/A return adaptor;
0N/A }
0N/A
0N/A private static AdaptorBootstrap getAdaptorBootstrap
0N/A (int port, int trapPort, String bindAddress, boolean useAcl,
0N/A String aclFileName) {
0N/A
0N/A final InetAddress address;
0N/A try {
0N/A address = InetAddress.getByName(bindAddress);
0N/A } catch (UnknownHostException e) {
0N/A throw new AgentConfigurationError(UNKNOWN_SNMP_INTERFACE, e, bindAddress);
0N/A }
0N/A if (log.isDebugOn()) {
0N/A log.debug("initialize",
0N/A Agent.getText("jmxremote.AdaptorBootstrap.getTargetList.starting" +
0N/A "\n\t" + PropertyNames.PORT + "=" + port +
0N/A "\n\t" + PropertyNames.TRAP_PORT + "=" + trapPort +
0N/A "\n\t" + PropertyNames.BIND_ADDRESS + "=" + address +
0N/A (useAcl?("\n\t" + PropertyNames.ACL_FILE_NAME + "="
0N/A + aclFileName):"\n\tNo ACL")+
0N/A ""));
0N/A }
0N/A
0N/A final InetAddressAcl acl;
0N/A try {
0N/A acl = useAcl ? new SnmpAcl(System.getProperty("user.name"),aclFileName)
0N/A : null;
0N/A } catch (UnknownHostException e) {
0N/A throw new AgentConfigurationError(UNKNOWN_SNMP_INTERFACE, e, e.getMessage());
0N/A }
0N/A
0N/A // Create adaptor
0N/A final SnmpAdaptorServer adaptor =
0N/A new SnmpAdaptorServer(acl, port, address);
0N/A adaptor.setUserDataFactory(new JvmContextFactory());
0N/A adaptor.setTrapPort(trapPort);
0N/A
0N/A // Create MIB
0N/A //
0N/A final JVM_MANAGEMENT_MIB_IMPL mib = new JVM_MANAGEMENT_MIB_IMPL();
0N/A try {
0N/A mib.init();
0N/A } catch (IllegalAccessException x) {
0N/A throw new AgentConfigurationError(SNMP_MIB_INIT_FAILED, x, x.getMessage());
0N/A }
0N/A
0N/A // Configure the trap destinations.
0N/A //
0N/A mib.addTargets(getTargetList(acl,trapPort));
0N/A
0N/A
0N/A // Start Adaptor
0N/A //
0N/A try {
0N/A // Will wait until the adaptor starts or fails to start.
0N/A // If the adaptor fails to start, a CommunicationException or
0N/A // an InterruptedException is thrown.
0N/A //
0N/A adaptor.start(Long.MAX_VALUE);
0N/A } catch (Exception x) {
0N/A Throwable t=x;
0N/A if (x instanceof com.sun.jmx.snmp.daemon.CommunicationException) {
0N/A final Throwable next = t.getCause();
0N/A if (next != null) t = next;
0N/A }
0N/A throw new AgentConfigurationError(SNMP_ADAPTOR_START_FAILED, t,
0N/A address + ":" + port,
0N/A "(" + t.getMessage() + ")");
0N/A }
0N/A
0N/A // double check that adaptor is actually started (should always
0N/A // be active, so that exception should never be thrown from here)
0N/A //
0N/A if (!adaptor.isActive()) {
0N/A throw new AgentConfigurationError(SNMP_ADAPTOR_START_FAILED,
0N/A address + ":" + port);
0N/A }
0N/A
0N/A try {
0N/A // Add MIB to adaptor
0N/A //
0N/A adaptor.addMib(mib);
0N/A
0N/A // Add Adaptor to the MIB
0N/A //
0N/A mib.setSnmpAdaptor(adaptor);
0N/A } catch (RuntimeException x) {
0N/A new AdaptorBootstrap(adaptor,mib).terminate();
0N/A throw x;
0N/A }
0N/A
0N/A log.debug("initialize",
0N/A Agent.getText("jmxremote.AdaptorBootstrap.getTargetList.initialize1"));
0N/A log.config("initialize",
0N/A Agent.getText("jmxremote.AdaptorBootstrap.getTargetList.initialize2",
0N/A address.toString(), java.lang.Integer.toString(adaptor.getPort())));
0N/A return new AdaptorBootstrap(adaptor,mib);
0N/A }
0N/A
0N/A private static void checkAclFile(String aclFileName) {
0N/A if (aclFileName == null || aclFileName.length()==0) {
0N/A throw new AgentConfigurationError(SNMP_ACL_FILE_NOT_SET);
0N/A }
0N/A final File file = new File(aclFileName);
0N/A if (!file.exists()) {
0N/A throw new AgentConfigurationError(SNMP_ACL_FILE_NOT_FOUND, aclFileName);
0N/A }
0N/A if (!file.canRead()) {
0N/A throw new AgentConfigurationError(SNMP_ACL_FILE_NOT_READABLE, aclFileName);
0N/A }
0N/A
0N/A FileSystem fs = FileSystem.open();
0N/A try {
0N/A if (fs.supportsFileSecurity(file)) {
0N/A if (!fs.isAccessUserOnly(file)) {
0N/A throw new AgentConfigurationError(SNMP_ACL_FILE_ACCESS_NOT_RESTRICTED,
0N/A aclFileName);
0N/A }
0N/A }
0N/A } catch (IOException e) {
0N/A throw new AgentConfigurationError(SNMP_ACL_FILE_READ_FAILED, aclFileName);
0N/A
0N/A }
0N/A }
0N/A
0N/A
0N/A /**
0N/A * Get the port on which the adaptor is bound.
0N/A * Returns 0 if the adaptor is already terminated.
0N/A *
0N/A **/
0N/A public synchronized int getPort() {
0N/A if (adaptor != null) return adaptor.getPort();
0N/A return 0;
0N/A }
0N/A
0N/A /**
0N/A * Stops the adaptor server.
0N/A **/
0N/A public synchronized void terminate() {
0N/A if (adaptor == null) return;
0N/A
0N/A // Terminate the MIB (deregister NotificationListener from
0N/A // MemoryMBean)
0N/A //
0N/A try {
0N/A jvmmib.terminate();
0N/A } catch (Exception x) {
0N/A // Must not prevent to stop...
0N/A //
0N/A log.debug("jmxremote.AdaptorBootstrap.getTargetList.terminate",
0N/A x.toString());
0N/A } finally {
0N/A jvmmib=null;
0N/A }
0N/A
0N/A // Stop the adaptor
0N/A //
0N/A try {
0N/A adaptor.stop();
0N/A } finally {
0N/A adaptor = null;
0N/A }
0N/A }
0N/A
0N/A}