Java tutorial
/* **************************************************************************** * Ldap Synchronization Connector provides tools to synchronize * electronic identities from a list of data sources including * any database with a JDBC connector, another LDAP directory, * flat files... * * ==LICENSE NOTICE== * * Copyright (c) 2008 - 2011 LSC Project * 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 the LSC Project nor 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. * * ==LICENSE NOTICE== * * (c) 2008 - 2011 LSC Project * Sebastien Bahloul <seb@lsc-project.org> * Thomas Chemineau <thomas@lsc-project.org> * Jonathan Clarke <jon@lsc-project.org> * Remy-Christophe Schermesser <rcs@lsc-project.org> **************************************************************************** */ package org.lsc.jmx; import java.io.IOException; import java.net.MalformedURLException; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.StringTokenizer; import javax.management.JMX; import javax.management.MBeanServerConnection; import javax.management.MalformedObjectNameException; import javax.management.Notification; import javax.management.NotificationListener; import javax.management.ObjectName; import javax.management.remote.JMXServiceURL; import javax.management.remote.rmi.RMIConnector; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.GnuParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.lang.ArrayUtils; import org.lsc.beans.SimpleBean; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * JMX Agent - Provide the ability to start/stop/get status of asynchronous * tasks * * By default this agent is only used on local call * * @author Sebastien Bahloul <seb@lsc-project.org> */ public class LscAgent implements NotificationListener { /** The local logger */ private static final Logger LOGGER = LoggerFactory.getLogger(LscAgent.class); /** When asking for an operation, this field contains the task */ private String taskName; /** The different asynchronous task operation types */ public enum OperationType { START, STOP, STATUS, TASKS_LIST, UNKNOWN, } /** The operation type */ private OperationType operation; /** Specify the URL */ private JMXServiceURL url; /** The RMI connector */ private RMIConnector jmxC; /** The MBean server connection */ private MBeanServerConnection jmxc; /** The LSC Server MBean */ private LscServer lscServer; /** The IP hostname */ private String hostname; /** The TCP port */ private String port; /** Identifier to synchronize */ private String idToSync; /** Identifier to synchronize */ private Map<String, String> attrsToSync; /** * Default constructor */ public LscAgent() { operation = OperationType.UNKNOWN; attrsToSync = new HashMap<String, String>(); } public static void main(String[] args) { LscAgent jmxAgent = new LscAgent(); int retCode = jmxAgent.parseOptions(args); if (retCode > 0) { System.exit(retCode); } System.exit(jmxAgent.run(jmxAgent.getOperation())); } public int run(OperationType operation) { if (!jmxBind()) { System.exit(1); return 1; } switch (operation) { case START: if (idToSync != null) { if (lscServer.launchSyncTaskById(taskName, idToSync, attrsToSync)) { LOGGER.info("Synchronization per id successfully achieved."); } else { LOGGER.error("Synchronization per id failed !"); return 2; } } else { lscServer.startAsyncTask(taskName); } break; case STOP: lscServer.shutdownAsyncTask(taskName); break; case STATUS: boolean status = lscServer.isAsyncTaskRunning(taskName); if (ArrayUtils.contains(lscServer.getAsyncTasksName(), taskName)) { LOGGER.info("Asynchronous task " + taskName + " is " + (status ? "running" : "stopped")); } else if (ArrayUtils.contains(lscServer.getSyncTasksName(), taskName)) { LOGGER.info("Synchronous task " + taskName + " is " + (status ? "running" : "stopped")); } else { LOGGER.error("Unknown or synchronous task name: " + taskName); return 3; } // Display full taks status if (status) { String fullStatus = lscServer.getTaskStatus(taskName); LOGGER.info(fullStatus); return 0; } return 1; case TASKS_LIST: LOGGER.info("Available asynchronous tasks are: "); for (String taskName : lscServer.getAsyncTasksName()) { LOGGER.info(" - " + taskName); } LOGGER.info("Available synchronous tasks are: "); for (String taskName : lscServer.getSyncTasksName()) { LOGGER.info(" - " + taskName); } break; default: } jmxUnbind(); return 0; } public boolean syncByObject(String taskName, String id, Map<String, List<String>> map) { if (!jmxBind()) { return false; } SimpleBean bean = new SimpleBean(); bean.setMainIdentifier(id); for (Entry<String, List<String>> entry : map.entrySet()) { bean.setDataset(entry.getKey(), new HashSet<Object>(Arrays.asList(entry.getValue().toArray()))); } return lscServer.launchSyncTask(taskName, bean); } /** * Manage command line options. * * @param args command line * @return the status code (0: OK, >=1 : failed) */ protected int parseOptions(final String[] args) { Options options = new Options(); options.addOption("a", "start", true, "Start an asynchronous task"); options.addOption("h", "hostname", true, "Specify the hostname to connect to"); options.addOption("l", "list", false, "List the available asynchronous tasks"); options.addOption("o", "stop", true, "Stop an asynchronous task"); options.addOption("p", "port", true, "Specify the port to connect to"); options.addOption("i", "identifier", true, "Specify the identifier to synchronize"); options.addOption("t", "attributes", true, "Specify the attributes pivot to synchronize (comma separated, identifier parameter required)"); options.addOption("s", "status", true, "Get a task status"); CommandLineParser parser = new GnuParser(); try { CommandLine cmdLine = parser.parse(options, args); if (cmdLine.hasOption("a")) { operation = OperationType.START; taskName = cmdLine.getOptionValue("a"); } if (cmdLine.hasOption("l")) { operation = OperationType.TASKS_LIST; } if (cmdLine.hasOption("o")) { operation = OperationType.STOP; taskName = cmdLine.getOptionValue("o"); } if (cmdLine.hasOption("s")) { operation = OperationType.STATUS; taskName = cmdLine.getOptionValue("s"); } if (cmdLine.hasOption("i")) { idToSync = cmdLine.getOptionValue("i"); if (cmdLine.hasOption("t")) { StringTokenizer attrsStr = new StringTokenizer(cmdLine.getOptionValue("t"), ","); while (attrsStr.hasMoreTokens()) { String token = attrsStr.nextToken(); if (token.contains("=")) { attrsToSync.put(token.substring(0, token.indexOf("=")), token.substring(token.indexOf("=") + 1)); } else { LOGGER.error( "Unknown attribute name=value couple in \"{}\". Please check your parameters !", token); printHelp(options); return 1; } } } } else if (cmdLine.hasOption("t")) { LOGGER.error("Attributes specified, but missing identifier !"); printHelp(options); return 1; } if (cmdLine.hasOption("h")) { hostname = cmdLine.getOptionValue("h"); } else { hostname = "localhost"; LOGGER.info("Hostname parameter not specified, using {} as default value.", hostname); } if (cmdLine.hasOption("p")) { port = cmdLine.getOptionValue("p"); } else { port = "1099"; LOGGER.info("TCP Port parameter not specified, using {} as default value.", port); } if (operation == OperationType.UNKNOWN) { printHelp(options); return 1; } } catch (ParseException e) { LOGGER.error("Unable to parse the options ({})", e.toString()); LOGGER.debug(e.toString(), e); return 1; } return 0; } /** * Print the command line help. * * @param options * specified options to manage */ private static void printHelp(final Options options) { HelpFormatter formatter = new HelpFormatter(); formatter.printHelp("lsc", options); } /** * Bind to the JMX Server */ public boolean jmxBind() { try { String sUrl = "service:jmx:rmi:///jndi/rmi://" + hostname + ":" + port + "/jmxrmi"; LOGGER.info("Connecting to remote engine on : " + sUrl); url = new JMXServiceURL(sUrl); jmxC = new RMIConnector(url, null); jmxC.connect(); jmxc = jmxC.getMBeanServerConnection(); ObjectName lscServerName = new ObjectName("org.lsc.jmx:type=LscServer"); lscServer = JMX.newMXBeanProxy(jmxc, lscServerName, LscServer.class, true); return true; } catch (MalformedObjectNameException e) { LOGGER.error(e.toString(), e); } catch (NullPointerException e) { LOGGER.error(e.toString(), e); } catch (MalformedURLException e) { LOGGER.error(e.toString(), e); } catch (IOException e) { LOGGER.error(e.toString(), e); } return false; } /** * Unbind from the JMX Server */ protected boolean jmxUnbind() { try { jmxC.close(); return true; } catch (IOException e) { LOGGER.error(e.toString(), e); } return false; } public void handleNotification(Notification notification, Object handback) { LOGGER.info("\nReceived notification: " + notification); } public OperationType getOperation() { return operation; } }