Package org.xmlBlaster.engine.admin

Source Code of org.xmlBlaster.engine.admin.CommandManager

/*------------------------------------------------------------------------------
Name:      CommandManager.java
Project:   xmlBlaster.org
Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
Comment:   Main manager class for administrative commands
------------------------------------------------------------------------------*/
package org.xmlBlaster.engine.admin;

import java.util.logging.Logger;
import java.util.logging.Level;
import org.xmlBlaster.util.MsgUnit;
import org.xmlBlaster.util.XmlBlasterException;
import org.xmlBlaster.util.admin.extern.JmxWrapper;
import org.xmlBlaster.util.context.ContextNode;
import org.xmlBlaster.util.def.ErrorCode;
import org.xmlBlaster.util.key.QueryKeyData;
import org.xmlBlaster.engine.ServerScope;
import org.xmlBlaster.engine.qos.AddressServer;
import org.xmlBlaster.engine.runlevel.RunlevelManager;
import org.xmlBlaster.engine.runlevel.I_RunlevelListener;
import org.xmlBlaster.authentication.SessionInfo;

import java.util.Map;
import java.util.TreeMap;

/**
* The manager instance for administrative commands.
* <p />
* Each xmlBlaster server instance has one instance
* of this class to manage its administrative behavior.
* <p />
* See the <a href="http://www.xmlBlaster.org/xmlBlaster/doc/requirements/admin.commands.html">command requirement</a>
* for a detailed description.
* @author xmlBlaster@marcelruff.info
* @since 0.79f
*/
public final class CommandManager implements I_RunlevelListener
{
   private final String ME;

   // The following 3 declarations are 'final' but the SUN JDK 1.3.1 does not like it
   private final ServerScope glob;
   private static Logger log = Logger.getLogger(CommandManager.class.getName());
   private final SessionInfo sessionInfo;

   /** Map to internal handlers like sysprop,client,msg etc */
   private final Map handlerMap = new TreeMap();

   /** Map of external gateways to SNMP, telnet etc. */
   private final Map externMap = new TreeMap();

   /**
    * You need to call postInit() after all drivers are loaded.
    *
    * @param sessionInfo Internal handle to be used directly with RequestBroker
    *                    NOTE: We (the command code) are responsible for security checks
    *                    as we directly write into RequestBroker.
    */
   public CommandManager(ServerScope glob, SessionInfo sessionInfo) {
      this.glob = glob;

      this.ME = "CommandManager" + this.glob.getLogPrefixDashed();
      this.sessionInfo = sessionInfo;
      glob.getRunlevelManager().addRunlevelListener(this);
   }

   /**
    * Create internal gateways.
    */
   private void initializeInternal() {
      // TODO: Change to use plugin framework:

      org.xmlBlaster.engine.admin.intern.PropertyHandler propertyHandler =
                             new org.xmlBlaster.engine.admin.intern.PropertyHandler();
      propertyHandler.initialize(glob, this); // This will call register()

      org.xmlBlaster.engine.admin.intern.CoreHandler coreHandler =
                             new org.xmlBlaster.engine.admin.intern.CoreHandler();
      coreHandler.initialize(glob, this); // This will call register()

      org.xmlBlaster.engine.admin.intern.MsgHandler msgHandler =
                             new org.xmlBlaster.engine.admin.intern.MsgHandler();
      msgHandler.initialize(glob, this); // This will call register()
   }

   private void initializeExternal() {
      // TODO: Change to use plugin framework:

      // Initialize telnet access ...
      try {
         org.xmlBlaster.engine.admin.extern.TelnetGateway telnetGateway = new org.xmlBlaster.engine.admin.extern.TelnetGateway();
  
         if (telnetGateway.initialize(glob, this) == true)
            this.externMap.put(telnetGateway.getName(), telnetGateway);
      }
      catch(XmlBlasterException e) {
         log.severe(e.getMessage());
      }
      catch(Throwable e) {
         e.printStackTrace();
         log.severe(e.toString());
      }

      // Initialize SNMP access ...
      try {
         org.xmlBlaster.engine.admin.extern.SnmpGateway snmpGateway = new org.xmlBlaster.engine.admin.extern.SnmpGateway();

         if (snmpGateway.initialize(glob, this) == true)
            this.externMap.put(snmpGateway.getName(), snmpGateway);
      }
      catch(XmlBlasterException e) {
         log.severe(e.getMessage());
      }
      catch(Throwable e) {
         e.printStackTrace();
         log.severe(e.toString());
      }

      // Initialize MomClient access ...
      try {
         org.xmlBlaster.engine.admin.extern.MomClientGateway momClientGateway = new org.xmlBlaster.engine.admin.extern.MomClientGateway();

         if (momClientGateway.initialize(glob, this) == true) {
            this.externMap.put(momClientGateway.getName(), momClientGateway);
            glob.registerMomClientGateway(momClientGateway);
         }
      }
      catch(XmlBlasterException e) {
         log.severe(e.getMessage());
      }
      catch(Throwable e) {
         e.printStackTrace();
         log.severe(e.toString());
      }
   }

   /**
    * Register internal handler for specific tasks.
    */
   public synchronized final void register(String key, I_CommandHandler handler) {
      if (key == null || handler == null) {
         Thread.dumpStack();
         throw new IllegalArgumentException(ME + ": Please pass a valid key and handler");
      }
      this.handlerMap.put(key, handler);
      if (log.isLoggable(Level.FINE)) log.fine("Registered '" + key + "' for handler=" + handler.getClass());
   }

   /**
    * @param sessionId Is null if not logged in
    * @param keyData the key containing the cmd.
    * @param qosData the qos. It can be null. It is null if the request comes
    *        from the telnet or snmp gateway (since in these cases the qos is
    *        wrapped inside the cmd, i.e. here it is inside the oid of the key).
    * @return The found data or an array of size 0 if not found.
    */
   public final MsgUnit[] get(AddressServer addressServer, String sessionId, QueryKeyData keyData, String querySpec) throws XmlBlasterException {
      String oid = keyData.getOid();
      if (log.isLoggable(Level.FINER)) log.finer("get(" + oid + ")");
      if (oid == null || oid.length() < 8) // "__cmd:" + 2 characters minimum
         throw new XmlBlasterException(glob, ErrorCode.USER_ILLEGALARGUMENT, ME, "Please pass a command which is not null or too short");
      // TODO: Change to use clientProperties arg1=..., arg2=...
      String[] args = (querySpec == null) ? new String[0] : new String[] { querySpec };
      return get(addressServer, sessionId, oid, args);
   }
   /**
    *
    * @param addressServer
    * @param sessionId
    * @param oid "__cmd:...."
    * @param args Can be null
    * @return
    * @throws XmlBlasterException
    */
   public final MsgUnit[] get(AddressServer addressServer, String sessionId, String oid, String[] args) throws XmlBlasterException {
      if (addressServer == null) {
         addressServer = this.sessionInfo.getAddressServer(); // uses requestBroker.unsecureSessionInfo
      }
      if (sessionId == null) {
         sessionId = this.sessionInfo.getSecuritySession().getSecretSessionId();
      }
      if (log.isLoggable(Level.FINER)) log.finer("get(" + oid + ")");
      if (oid == null || oid.length() < 8) // "__cmd:" + 2 characters minimum
         throw new XmlBlasterException(glob, ErrorCode.USER_ILLEGALARGUMENT, ME, "Please pass a command which is not null or too short");

      String cmd = CommandWrapper.stripCommand(this.glob, oid);
      if (cmd.startsWith(ContextNode.SCHEMA_JMX_DOMAIN)) { // JMX query starts with "org.xmlBlaster:"
         // ObjectName = org.xmlBlaster:nodeClass=node,node="heron"
         // org.xmlBlaster:nodeClass=node,node="heron"/action=getFreeMemStr
         // org.xmlBlaster:nodeClass=node,node="heron"/action=usage?action=usage
        
         // java  -Djmx.invoke.getters=set ... org.xmlBlaster.Main
         // org.xmlBlaster:nodeClass=node,node="heron"/action=getLastWarning?action=getLastWarning
         // org.xmlBlaster:nodeClass=node,node="heron"/action=getLastWarning
         // org.xmlBlaster:nodeClass=node,node="avalon_mycomp_com",clientClass=client,client="heron.mycomp.com",sessionClass=session,session="1"/action=getConnectionState
         Object obj = JmxWrapper.getInstance(this.glob).invokeCommand(cmd);
         StringBuffer ret = new StringBuffer(1024);
         if (obj != null) {
            if (obj instanceof MsgUnit) {
               return new MsgUnit[] { (MsgUnit)obj };
            }
            else if (obj instanceof MsgUnit[]) {
               return (MsgUnit[])obj;
            }
            else if (obj instanceof String[]) {
               String[] str = (String[])obj;
               for(int i=0; i<str.length; i++)
                  ret.append(str[i]).append("\n");
            }
            else {
               ret.append(obj);
            }
         }
         MsgUnit msgUnit = new MsgUnit("<key oid='__cmd:"+cmd+"'/>", ret.toString().getBytes(), "<qos/>");
         return new MsgUnit[] { msgUnit };
      }
     
      try {
         CommandWrapper w = new CommandWrapper(glob, oid);
         if (args != null) w.setArgs(args);
         String key = w.getThirdLevel();
         if (w.getThirdLevel().startsWith("?")) {
            key = "DEFAULT"// One handler needs to register itself with "DEFAULT"
         }
         Object obj = this.handlerMap.get(key); // e.g. "topic" or "client" or "sysprop"
         if (obj == null) {
            throw new XmlBlasterException(glob, ErrorCode.USER_ILLEGALARGUMENT, ME, "Sorry can't process your command '" + oid + "', '" + w.getThirdLevel() + "' has no registered handler (key=" + key + ")");
         }
         I_CommandHandler handler = (I_CommandHandler)obj;
         MsgUnit[] ret = handler.get(addressServer, sessionId, w);
         if (ret == null) ret = new MsgUnit[0];
         return ret;
         //return (ret==null) ? "<qos><state id='NOT_FOUND' info='" + w.getCommand() + " has no results.'/></qos>" : ret;
      }
      catch (XmlBlasterException e) {
         throw e;
      }
      catch (Throwable e) {
         e.printStackTrace();
         throw XmlBlasterException.convert(glob, ME, "get("+oid+")", e);
      }
   }

   /**
    * @param sessionId Is null if not logged in
    * @param cmd The query string
    * @return The SetReturn object:<br />
    *         setReturn.returnString contains the actually set value or is null if not set.
    */
   public final SetReturn set(AddressServer addressServer,
                String sessionId, String cmd) throws XmlBlasterException {
      if (addressServer == null) {
         addressServer = this.sessionInfo.getAddressServer(); // uses requestBroker.unsecureSessionInfo
      }
      if (sessionId == null) {
         sessionId = this.sessionInfo.getSecuritySession().getSecretSessionId();
      }
      if (log.isLoggable(Level.FINER)) log.finer("set(" + cmd + ")");
      if (cmd == null || cmd.length() < 1)
         throw new XmlBlasterException(glob, ErrorCode.USER_ILLEGALARGUMENT, ME, "Please pass a command which is not null");
     
     
      if (cmd.startsWith(ContextNode.SCHEMA_JMX_DOMAIN)) { // JMX query starts with "org.xmlBlaster:"
         // ObjectName = org.xmlBlaster:nodeClass=node,node="heron"
         // org.xmlBlaster:nodeClass=node,node="heron"/action=getFreeMemStr
         // org.xmlBlaster:nodeClass=node,node="heron"/action=usage?action=usage
        
         // java  -Djmx.invoke.getters=set ... org.xmlBlaster.Main
         // org.xmlBlaster:nodeClass=node,node="heron"/action=getLastWarning?action=getLastWarning
         // org.xmlBlaster:nodeClass=node,node="heron"/action=getLastWarning
         // org.xmlBlaster:nodeClass=node,node="avalon_mycomp_com",clientClass=client,client="heron.mycomp.com",sessionClass=session,session="1"/action=getConnectionState
         Object obj = JmxWrapper.getInstance(this.glob).invokeCommand(cmd);
         StringBuffer ret = new StringBuffer(1024);
         if (obj != null) {
            if (obj instanceof String[]) {
               String[] str = (String[])obj;
               for(int i=0; i<str.length; i++)
                  ret.append(str[i]).append("\n");
            }
            else {
               ret.append(obj);
            }
         }
         return new SetReturn(null, ret.toString());
      }

      try {
         CommandWrapper w = new CommandWrapper(glob, cmd);
         String key = w.getThirdLevel();
         if (w.getThirdLevel().startsWith("?")) {
            key = "DEFAULT"// One handler needs to register itself with "DEFAULT"
         }
         Object obj = this.handlerMap.get(key);
         if (obj == null) {
            throw new XmlBlasterException(glob, ErrorCode.USER_ILLEGALARGUMENT, ME, "Sorry can't process your command '" + cmd + "', the third level '" + w.getThirdLevel() + "' has no registered handler (key=" + key + ")");
         }
         I_CommandHandler handler = (I_CommandHandler)obj;
         return new SetReturn(w, handler.set(addressServer, sessionId, w));
      }
      catch (XmlBlasterException e) {
         throw e;
      }
      catch (Throwable e) {
         e.printStackTrace();
         throw XmlBlasterException.convert(glob, ME, "set("+cmd+")", e);
      }
   }

   /**
    */
   public String help() {
      return "  XmlBlaster administration, see http://www.xmlblaster.org/xmlBlaster/doc/requirements/admin.commands.html";
   }

   /**
    */
   public String help(String cmd) {
      return help();
   }

   public void shutdown() {
      if (this.externMap != null && this.externMap.size() > 0) {
         I_ExternGateway[] arr = (I_ExternGateway [])this.externMap.values().toArray(new I_ExternGateway[this.externMap.size()]);
         for (int ii=0; ii<arr.length; ii++) {
            arr[ii].shutdown();
         }
         externMap.clear();
      }

      if (this.handlerMap != null && this.handlerMap.size() > 0) {
         I_CommandHandler[] arr = (I_CommandHandler [])this.handlerMap.values().toArray(new I_CommandHandler[this.handlerMap.size()]);
         for (int ii=0; ii<arr.length; ii++) {
            arr[ii].shutdown()// If a handler has registered multiple times, it should be able to handle multiple shutdowns
         }
         this.handlerMap.clear();
      }
   }

   /**
    * A human readable name of the listener for logging.
    * <p />
    * Enforced by I_RunlevelListener
    */
   public String getName() {
      return ME;
   }

   /**
    * Invoked on run level change, see RunlevelManager.RUNLEVEL_HALTED and RunlevelManager.RUNLEVEL_RUNNING
    * <p />
    * Enforced by I_RunlevelListener
    */
   public void runlevelChange(int from, int to, boolean force) throws org.xmlBlaster.util.XmlBlasterException {
      if (log.isLoggable(Level.FINER)) log.finer("Changing from run level=" + from + " to level=" + to + " with force=" + force);
      if (to == from)
         return;

      if (to > from) { // startup
         if (to == RunlevelManager.RUNLEVEL_STANDBY) {
            initializeInternal();
            initializeExternal();
            log.info("Administration manager is ready");
         }
      }

      if (to < from) { // shutdown
         if (to == RunlevelManager.RUNLEVEL_HALTED) {
            shutdown();
         }
      }
   }

   /**
    * Dump state of this object into a XML ASCII string.
    */
   public final String toXml() {
      return toXml((String)null);
   }

   /**
    * Dump state of this object into a XML ASCII string.
    * @param extraOffset indenting of tags for nice output
    */
   public synchronized final String toXml(String extraOffset) {
      StringBuffer sb = new StringBuffer(1024);
      String offset = "\n   ";
      if (extraOffset == null) extraOffset = "";
      offset += extraOffset;

      sb.append(offset).append("<commandManager>");
      /*
      if (externMap != null && externMap.size() > 0) {
         Iterator it = externMap.values().iterator();
         while (it.hasNext()) {
            I_ExternGatewax gw = (I_ExternGateway)it.next();
            sb.append(gw.toXml(extraOffset + "   "));
         }
         externMap.clear();
      }
      if (handlerMap != null && handlerMap.size() > 0) {
         Iterator it = handlerMap.values().iterator();
         while (it.hasNext()) {
            I_CommandHandler cmd = (I_CommandHandler)it.next();
            sb.append(cmd.toXml(extraOffset + "   "));
         }
      }
      */
      sb.append(offset).append("</commandManager>");

      return sb.toString();
   }
}
TOP

Related Classes of org.xmlBlaster.engine.admin.CommandManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.