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.*; import javax.management.remote.*; import javax.management.remote.rmi.*; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; import java.util.HashMap; import java.util.Hashtable; import java.util.List; import java.util.ArrayList; import java.util.Locale; import java.util.Vector; import java.io.IOException; import java.io.Serializable; import java.net.InetAddress; import java.net.MalformedURLException; /** * This class demonstrates how to use an LDAP directory as a lookup * service for JSR 160 connectors. It shows how to register a * JMXConnectorServer with the LDAP directory through JNDI. *
* 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 Server { // The URL will remain registered for 60 secs. // public final static int JMX_DEFAULT_LEASE = 60; private static boolean debug = false; /** * The local MBeanServer. */ private final MBeanServer mbs; /** * Constructs a Server object. Creates a new MBeanServer. */ public Server() { mbs = MBeanServerFactory.createMBeanServer(); } /** * 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: *
"com.sun.jndi.ldap.LdapCtxFactory"
"cn=Directory Manager"
* If the given DN does not point to an existing node in the * directory, then this method will attempt to create it. Yet, * the parent node must already exist in that case. *
* If the DN points to a node that is already of the jmxConnector
* class, then this method will simply override its jmxServiceURL
* ,jmxAgentName, jmxProtocolType,
* jmxAgentHost and jmxExpirationDate attributes.
*
* @param root A pointer to the root context we are using,
* as returned by {@link #getRootContext()}.
* @param jmxUrl A JMX Connector Server URL, that should have
* been obtained from
* {@link JMXConnectorServer#getAddress()
* JMXConnectorServer.getAddress()};
* @param name The AgentName with which the URL must be registered
* in the LDAP directory.
*/
public static void register(DirContext root,
JMXServiceURL jmxUrl,
String name)
throws NamingException, IOException {
// Get the LDAP DN where to register
//
final String mydn = System.getProperty("dn","cn="+name);
debug("dn: " + mydn );
// First check whether
* This method will transfer a fixed set of System Properties to
* the Map given to the RMIConnectorServer constructor. Some
* JNDI properties, if defined, are transfered to the Map so
* that they may be used when LDAP is used as external directory
* to register the RMI Stub (see {@link javax.management.remote.rmi}
* Javadoc). Note that even if LDAP is used as external directory
* the {@link Context#INITIAL_CONTEXT_FACTORY
* Context.INITIAL_CONTEXT_FACTORY} and
* {@link Context#PROVIDER_URL Context.PROVIDER_URL} properties
* usually don't need to be passed.
*
* The following System properties, if defined, are transfered to
* the Map given to the RMIConnectorServer constructor.
*
* Creates a server object, gets the JMX Service URL, and calls
* the method that will create and register the appropriate
* JMX Connector Server for that URL.
*
* You may wish to use the following properties on the Java command line:
*
*
* @param url A string representation of the JMXServiceURL.
* @return the created RMIConnectorServer.
*/
public JMXConnectorServer rmi(String url)
throws IOException, JMException,
NamingException, ClassNotFoundException {
// Make a JMXServiceURL from the url string.
//
JMXServiceURL jurl = new JMXServiceURL(url);
// Prepare the environment Map
//
final HashMap env = new HashMap();
final String rprop = RMIConnectorServer.JNDI_REBIND_ATTRIBUTE;
final String rebind=System.getProperty(rprop,"true");
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);
env.put(rprop,rebind); // default is true.
// Create an RMIConnectorServer
//
System.out.println("Creating RMI Connector: " + jurl);
JMXConnectorServer rmis =
JMXConnectorServerFactory.newJMXConnectorServer(jurl, env, mbs);
// Get the AgentName for registering the Connector in the Lookup Service
//
final String agentName = System.getProperty("agent.name",
"DefaultAgent");
// Start the connector and register it in the LDAP directory.
//
start(rmis,env,agentName);
return rmis;
}
/**
* Start a JMXConnectorServer and register it with the LDAP directory.
*
* @param server the JMXConnectorServer to start and register.
* @param env the environment Map.
* @param agentName the AgentName with which the URL must be registered
* in the LDAP Directory. This is not a LDAP DN, but
* the value of the jmxAgentName attribute.
*/
public void start(JMXConnectorServer server, Map env, String agentName)
throws IOException, NamingException {
// Start the JMXConnectorServer
//
server.start();
// Get a pointer to the LDAP directory.
//
final DirContext root = getRootContext();
// Create a JMX Service URL to register in the LDAP directory
//
final JMXServiceURL address = server.getAddress();
// Register the URL in the LDAP directory
//
register(root,address,agentName);
}
/**
* Returns a X.208 string representing the GMT date at now + sec.
*
* @param sec Number of seconds from now.
* @return an X.208 GMT GeneralizedTime (ending with Z).
*/
public static String getExpirationDate(long sec) {
final SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMddHHmmss.S");
final Date date = new Date();
final Date gmtDate;
if (fmt.getCalendar().getTimeZone().inDaylightTime(date))
gmtDate = new Date(System.currentTimeMillis() -
fmt.getCalendar().getTimeZone().getRawOffset() -
fmt.getCalendar().getTimeZone().getDSTSavings() +
1000*sec);
else
gmtDate =
new Date(System.currentTimeMillis() -
fmt.getCalendar().getTimeZone().getRawOffset() +
1000*sec);
return ((fmt.format(gmtDate))+"Z");
}
/**
* Trace a debug message.
*/
private static void debug(String msg) {
if (debug) System.out.println(msg);
}
/**
* Program Main
* true
.
*
*/
public static void main(String[] args) {
try {
// Get the value of the debug flag.
//
debug = (Boolean.valueOf(System.getProperty("debug","false"))).
booleanValue();
// Create a new Server object.
//
final Server s = new Server();
// Get the JMXConnector URL
//
final String url =
System.getProperty("url", "service:jmx:rmi://");
// Build a JMXServiceURL
//
final JMXServiceURL jurl = new JMXServiceURL(url);
// Creates a JMX Connector Server
//
final JMXConnectorServer server;
debug("Creating Connector: " + jurl);
final String p = jurl.getProtocol();
if (p.equals("rmi")) // Create an RMI Connector
s.rmi(url);
else if (p.equals("iiop")) // Create an RMI/IIOP Connector
s.rmi(url);
else // Unsupported protocol
throw new MalformedURLException("Unsupported protocol: " + p);
System.out.println("\nService URL successfully registered " +
"in the LDAP Lookup Service");
} catch (Exception x) {
System.err.println("Unexpected exception caught in main: " + x);
x.printStackTrace(System.err);
}
}
}
-Durl=<jmxServiceURL>
: specifies the URL of
* the JMX Connector Server you wish to use. See README file for more
* details.-Dagent.name=<AgentName>
: specifies an
* AgentName to register with.-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")