/* * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of Oracle or the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package jndi; import javax.naming.InitialContext; import javax.naming.Context; import javax.naming.NamingEnumeration; import javax.naming.NameNotFoundException; import javax.naming.NamingException; import javax.naming.directory.DirContext; import javax.naming.directory.Attribute; import javax.naming.directory.BasicAttribute; import javax.naming.directory.Attributes; import javax.naming.directory.BasicAttributes; import javax.naming.directory.DirContext; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.SearchResult; import javax.naming.directory.SearchControls; import javax.naming.ldap.InitialLdapContext; import javax.management.remote.*; import javax.management.*; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; import java.util.List; import java.util.ArrayList; import java.util.HashMap; import java.util.Hashtable; import java.util.Set; import java.util.Iterator; import java.util.Locale; import java.util.Vector; import java.io.IOException; import java.io.Serializable; /** * This class demonstrates how to use an LDAP directory as a lookup service * for JSR 160 connectors. It shows how to lookup a JMXServiceURL * from the LDAP directory. *

* See README file and {@link #main(String[])} for more details. *

* Make sure to read the section "Binding with Lookup Services" of * the JMX Remote API 1.0 Specification before looking at this example. */ public class Client { private static boolean debug = false; /** * List all the attributes of an LDAP node. * * @param root The root DirContext. * @param dn The DN of the node, relative to the root DirContext. */ public static void listAttributes(DirContext root, String dn) throws NamingException { final Attributes attrs = root.getAttributes(dn); System.out.println("dn: " + dn); System.out.println("attributes: " + attrs); } /** * Get a pointer to the root context of the directory tree * under which this server is supposed to register itself. * All LDAP DNs will be considered to be relative to that root. *

* Note that this root is not part of the JSR 160 specification, * since the actual location where a JMX Agent will register * its connectors is left completely open by the specification. * The specification only discuss what the JMX Agent must/may * put in the directory - but not where. *

* This method assumes that the root of the directory is * will be passed in a the {@link Context#PROVIDER_URL * Context.PROVIDER_URL} System property. *

* This method will transfer a fixed set of System Properties to * the Hashtable given to the JNDI InitialContext: *

* * @return a pointer to the LDAP Directory. */ public static DirContext getRootContext() throws NamingException { // Prepare environment // final Hashtable env = new Hashtable(); // The Initial Context Factory must be provided, and // must point to an LDAP Context Factory // final String factory = System.getProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); // The LDAP Provider URL must be provided, and // must point to a running LDAP directory server // final String ldapServerUrl = System.getProperty(Context.PROVIDER_URL); // The LDAP user must be provided, and // must have write access to the subpart of the directory // where the agent will be registered. // final String ldapUser = System.getProperty(Context.SECURITY_PRINCIPAL, "cn=Directory Manager"); // Credentials must be provided, so that the user may // write to the directory. // final String ldapPasswd = System.getProperty(Context.SECURITY_CREDENTIALS); // Debug info: print provided values: // debug(Context.PROVIDER_URL + "=" + ldapServerUrl); debug(Context.SECURITY_PRINCIPAL + "=" + ldapUser); if (debug) { System.out.print(Context.SECURITY_CREDENTIALS + "="); final int len = (ldapPasswd==null)?0:ldapPasswd.length(); for (int i=0;iprotocolType is null, * then the jmxProtocolType attribute is ignored. Otherwise, * only those agents that have registered a matching * jmxProtocolType attribute will be returned. * @param name the AgentName of the JMXConnectors that should * be returned. If name is null, then * the JMXConnectors for all agents are returned * (null is an equivalent for a wildcard). * @return The list of matching JMXConnectors retrieved from * the LDAP directory. */ public static List lookup(DirContext root, String protocolType, String name) throws IOException, NamingException { final ArrayList list = new ArrayList(); // If protocolType is not null, include it in the filter. // String queryProtocol = (protocolType==null)?"":"(jmxProtocolType="+protocolType+")"; // Set the LDAPv3 query string // // Only those node that have the jmxConnector object class are // of interest to us, so we specify (objectClass=jmxConnector) // in the filter. // // We specify the jmxAgentName attribute in the filter so that the // query will return only those services for which the AgentName // attribute was registered. Since JSR 160 specifies that // the AgentName attribute is mandatory, this makes it possible // to filter out all the services that do not conform // to the spec. // If is null, it is replaced by "*", so that all // services for which the AgentName attribute was specified match, // regardless of the value of that attribute. // Otherwise, only those services for which AgentName matches the // name or pattern specified by will be returned. // // We also specify (jmxServiceURL=*) so that only those node // for which the jmxServiceURL attribute is present will be // returned. Thus, we filter out all those node corresponding // to agents that are not currently available. // String query = "(&" + "(objectClass=jmxConnector) " + "(jmxServiceURL=*) " + queryProtocol + "(jmxAgentName=" + ((name!=null)?name:"*") + "))"; System.out.println("Looking up JMX Agents with filter: " + query ); SearchControls ctrls = new SearchControls(); // Want to get all jmxConnector objects, wherever they've been // registered. // ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE); // Want to get only the jmxServiceUrl and jmxExpirationDate // (comment these lines and all attributes will be returned). // // ctrls.setReturningAttributes(new String[] { // "jmxServiceURL", // "jmxExpirationDate" // }); // Search... // final NamingEnumeration results = root.search("", query, ctrls); // Get the URL... // while (results.hasMore()) { // Get node... // final SearchResult r = (SearchResult) results.nextElement(); debug("Found node: " + r.getName()); // Get attributes // final Attributes attrs = r.getAttributes(); // Get jmxServiceURL attribute // final Attribute attr = attrs.get("jmxServiceURL"); if (attr == null) continue; // Get jmxExpirationDate // final Attribute exp = attrs.get("jmxExpirationDate"); // Check that URL has not expired. // if ((exp != null) && hasExpired((String)exp.get())) { System.out.print(r.getName() + ": "); System.out.println("URL expired since: " + exp.get()); continue; } // Get the URL string // final String urlStr = (String)attr.get(); if (urlStr.length() == 0) continue; debug("Found URL: " + urlStr); // Create a JMXServiceURL // final JMXServiceURL url = new JMXServiceURL(urlStr); // Create a JMXConnector // final JMXConnector conn = JMXConnectorFactory.newJMXConnector(url,null); // Add the connector to the result list // list.add(conn); if (debug) listAttributes(root,r.getName()); } return list; } /** * List all MBeans and their attributes. */ public static void listMBeans(MBeanServerConnection server) throws IOException { final Set names = server.queryNames(null,null); for (final Iterator i=names.iterator(); i.hasNext(); ) { ObjectName name = (ObjectName)i.next(); System.out.println("Got MBean: "+name); try { MBeanInfo info = server.getMBeanInfo((ObjectName)name); MBeanAttributeInfo[] attrs = info.getAttributes(); if (attrs == null) continue; for (int j=0; j * Lookup all JMX agents in the LDAP Directory and list * their MBeans and attributes. *

* You may wish to use the following properties on the Java command line: *

    *
  • -Dagent.name=<AgentName>: specifies an * AgentName to lookup (default is null, meaning any agent).
  • *
  • -Dprotocol=<ProtocolType>: restrains the client * to lookup for a specific protocol type (default is null, * meaning any type).
  • *
  • -Djava.naming.factory.initial=<initial-context-factory> * : The initial context factory to use for accessing the * LDAP directory (see {@link Context#INITIAL_CONTEXT_FACTORY * Context.INITIAL_CONTEXT_FACTORY}) - default is * "com.sun.jndi.ldap.LdapCtxFactory".
  • *
  • -Djava.naming.provider.url=<provider-url>: * The LDAP Provider URL (see {@link Context#PROVIDER_URL * Context.PROVIDER_URL}).
  • *
  • -Djava.naming.security.principal=<ldap-principal> * : The security principal (login) to use to connect with * the LDAP directory (see {@link Context#SECURITY_PRINCIPAL * Context.SECURITY_PRINCIPAL} - default is * "cn=Directory Manager".
  • *
  • -Djava.naming.security.credentials=<ldap-credentials> * : The security credentials (password) to use to * connect with the LDAP directory (see * {@link Context#SECURITY_CREDENTIALS * Context.SECURITY_CREDENTIALS}).
  • *
  • -Ddebug="true|false": switch the Server debug flag * on/off (default is "false")
  • *
*/ public static void main(String[] args) { try { // Get the value of the debug flag. // debug = (Boolean.valueOf(System.getProperty("debug","false"))). booleanValue(); // Get a pointer to the LDAP Directory. // final DirContext root = getRootContext(); debug("root is: " + root.getNameInNamespace()); final String protocolType=System.getProperty("protocol"); final String agentName=System.getProperty("agent.name"); // Lookup all matching agents in the LDAP Directory. // List l = lookup(root,protocolType,agentName); // Attempt to connect to retrieved agents // System.out.println("Number of agents found : " + l.size()); int j = 1; for (Iterator i=l.iterator();i.hasNext();j++) { JMXConnector c1 = (JMXConnector) i.next(); if (c1 != null) { // Connect // System.out.println( "----------------------------------------------------"); System.out.println("\tConnecting to agent number "+j); System.out.println( "----------------------------------------------------"); debug("JMXConnector is: " + c1); // Prepare the environment Map // final HashMap env = new HashMap(); final String factory = System.getProperty(Context.INITIAL_CONTEXT_FACTORY); final String ldapServerUrl = System.getProperty(Context.PROVIDER_URL); final String ldapUser = System.getProperty(Context.SECURITY_PRINCIPAL); final String ldapPasswd = System.getProperty(Context.SECURITY_CREDENTIALS); // Transfer some system properties to the Map // if (factory!= null) // this should not be needed env.put(Context.INITIAL_CONTEXT_FACTORY,factory); if (ldapServerUrl!=null) // this should not be needed env.put(Context.PROVIDER_URL, ldapServerUrl); if (ldapUser!=null) // this is needed when LDAP is used env.put(Context.SECURITY_PRINCIPAL, ldapUser); if (ldapPasswd != null) // this is needed when LDAP is used env.put(Context.SECURITY_CREDENTIALS, ldapPasswd); try { c1.connect(env); } catch (IOException x) { System.err.println("Connection failed: " + x); x.printStackTrace(System.err); continue; } // Get MBeanServerConnection // MBeanServerConnection conn = c1.getMBeanServerConnection(); debug("Connection is:" + conn); System.out.println("Server domain is: " + conn.getDefaultDomain()); // List all MBeans // try { listMBeans(conn); } catch (IOException x) { System.err.println("Failed to list MBeans: " + x); x.printStackTrace(System.err); } // Close connector // try { c1.close(); } catch (IOException x) { System.err.println("Failed to close connection: " + x); x.printStackTrace(System.err); } } } } catch (Exception x) { System.err.println("Unexpected exception caught in main: " + x); x.printStackTrace(System.err); } } }