Package fr.dyade.aaa.agent

Source Code of fr.dyade.aaa.agent.AdminProxy

/*
* Copyright (C) 2001 - 2008 ScalAgent Distributed Technologies
* Copyright (C) 1996 - 2000 BULL
* Copyright (C) 1996 - 2000 INRIA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
* USA.
*/
package fr.dyade.aaa.agent;

import java.io.*;
import java.net.*;
import java.util.*;
import java.lang.reflect.*;

import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;

import fr.dyade.aaa.agent.conf.A3CML;
import fr.dyade.aaa.agent.conf.A3CMLConfig;
import fr.dyade.aaa.common.Daemon;

/**
* A <code>AdminProxy</code> service provides a TCP service allowing remote
* administration of agent servers.
* <p>
* The <code>AdminProxy</code> service can be configured by the way of
* service argument:
* <ul>
* <li>the TCP port number, by default this port is 8091.
* <li>the number of monitor needed to handled requests.
* </ul>
*/
public class AdminProxy {

  static AdminProxy proxy = null;

  public static boolean debug = true;

  /** Property that define the TCP listen port */
  public final static String LISTENPORT = "fr.dyade.aaa.agent.AdminProxy.port";
  /** The TCP listen port, by default 8091 */
  private static int port = 8091;
  /** The number of monitors.*/
  private static int nbm;
  /** Property that define the number of monitor */
  public final static String NBMONITOR = "fr.dyade.aaa.agent.AdminProxy.nbm";
  /** Hashtable that contain all <code>Process</code> of running AgentServer */
  //   Hashtable ASP = null;

  AdminMonitor monitors[] = null;
  ServerSocket listen = null;

  static Logger xlogmon = null;

  /**
   * Initializes the package as a well known service.
   * <p>
   * Creates a <code>AdminProxy</code> proxy listen on .
   *
   * @param args  parameters from the configuration file
   * @param firstTime  <code>true</code> when service starts anew
   */
  public static void init(String args, boolean firstTime) throws Exception {
    try {
      if (args.length()!=0) {
        port = Integer.parseInt(args);
      } else {
        port = Integer.parseInt(AgentServer.getProperty(LISTENPORT, "8091"));
      }
    } catch (NumberFormatException exc) {
      port = 8091;
    }

    try {
      nbm = Integer.parseInt(AgentServer.getProperty(NBMONITOR, "1"));
    } catch (NumberFormatException exc) {
      nbm = 1;
    }

    // Get the logging monitor from current server MonologMonitorFactory
    xlogmon = Debug.getLogger(Debug.A3Service + ".AdminProxy" +
                              ".#" + AgentServer.getServerId());

    if (proxy != null) {
      xlogmon.log(BasicLevel.ERROR,
                  "AdminProxy#" + AgentServer.getServerId() +
      ": already initialized.");
      throw new Exception("AdminProxy" + ".#" + AgentServer.getServerId() +
      ": already initialized.");
    }

    try {
      proxy = new AdminProxy();
    } catch (IOException exc) {
      xlogmon.log(BasicLevel.ERROR,
                  "AdminProxy#" + AgentServer.getServerId() +
                  ", can't get listen port", exc);
      throw exc;
    }
    start();
  }

  /**
   * Creates an AdminProxy service.
   *
   * @param port  TCP listen port of this proxy
   */
  private AdminProxy() throws IOException {
    for (int i=0; ; i++) {
      try {
        listen = new ServerSocket(port);
        break;
      } catch (BindException exc) {
        if (i > 5) throw exc;
        try {
          // Wait ~15s: n*(n+1)*500 ms with n=5
          Thread.sleep(i * 500);
        } catch (InterruptedException e) {}
      }
    }

    //     ASP = new Hashtable();

    monitors = new AdminMonitor[nbm];
    for (int i=0; i<monitors.length; i++) {
      monitors[i] = new AdminMonitor("AdminProxy#" +
                                     AgentServer.getServerId() + '.' + i);
    }
  }

  public static void start() {
    for (int i=0; i<proxy.monitors.length; i++) {
      proxy.monitors[i].start();
    }
  }

  public static void stopService() {
    for (int i=0; i<proxy.monitors.length; i++) {
      if (proxy.monitors[i] != null) proxy.monitors[i].stop();
      proxy.monitors[i] = null;
    }
    proxy = null;
  }

  static final String HELP = "help";
  static final String NONE = "";

  // Server's administration commands
  public static final String STOP_SERVER = "halt";
  public static final String CRASH_SERVER = "crash";
  public static final String PING = "ping";
  public static final String CONFIG = "config";

  // Environment control
  static final String SET_VARIABLE = "set";
  static final String GET_VARIABLE = "get";

  // JVM's monitoring and control
  static final String GC = "gc";
  static final String THREADS = "threads";

  // Consumer's administration commands
  static final String LIST_MCONS = "consumers";
  static final String START_MCONS = "start";
  static final String STOP_MCONS = "stop";

  // Service's administration commands
  static final String LIST_SERVICE = "services";
  static final String ADD_SERVICE = "add";
  static final String REMOVE_SERVICE = "remove";

  // Debug's tool
  static final String DUMP = "dump";

  // update traces configuration
  public static final String LOG = "log";

  /**
   * Provides a string image for this object.
   */
  public String toString() {
    StringBuffer strBuf = new StringBuffer();

    strBuf.append("(").append(super.toString());
    strBuf.append(",port=").append(port);
    strBuf.append(",monitors=[");
    for (int i=0; i<monitors.length; i++) {
      strBuf.append(monitors[i].toString()).append(",");
    }
    strBuf.append("]");
    strBuf.append(")");

    return strBuf.toString();
  }

  class AdminMonitor extends Daemon {
    Socket socket = null;
    BufferedReader reader = null;
    PrintWriter writer = null;

    /**
     * Constructor.
     */
    protected AdminMonitor(String name) {
      // Get the logging monitor from AdminProxy (overload Daemon setup)
      super(name, AdminProxy.xlogmon);
      this.setThreadGroup(AgentServer.getThreadGroup());
    }

    /**
     * Provides a string image for this object.
     *
     * @return  printable image of this object
     */
    public String toString() {
      return "(" + super.toString() +
      ",socket=" + socket + ")";
    }

    public void run() {
      try {
        while (running) {
          canStop = true;
          try {
            logmon.log(BasicLevel.DEBUG, getName() + ", waiting: " + listen);
            socket = listen.accept();
            logmon.log(BasicLevel.DEBUG, getName() + ", receiving.");
            canStop = false;
          } catch (IOException exc) {
            if (running)
              logmon.log(BasicLevel.ERROR,
                         getName() + ", error during accept", exc);
          }

          if (! running) break;

          try {
            // Get the streams
            reader = new BufferedReader(
                                        new InputStreamReader(socket.getInputStream()));
            writer = new PrintWriter(socket.getOutputStream(), true);

            // Reads then parses the request
            doRequest(reader.readLine());

            writer.flush();
          } catch (Exception exc) {
            logmon.log(BasicLevel.ERROR,
                       getName() + ", error during connection", exc);
          } finally {
            // Closes the connection
            try {
              reader.close();
            } catch (Exception exc) {}
            reader = null;
            try {
              writer.close();
            } catch (Exception exc) {}
            writer = null;
            try {
              socket.close();
            } catch (Exception exc) {}
            socket = null;
          }
        }
      } finally {
        logmon.log(BasicLevel.DEBUG, getName() + ", finishing.");
        finish();
      }
    }

    protected void close() {
      try {
        logmon.log(BasicLevel.DEBUG, getName() + ", closing: " + listen);
        listen.close();
      } catch (Exception exc) {}
      listen = null;
    }

    protected void shutdown() {
      logmon.log(BasicLevel.DEBUG, getName() + ", close(): ");
      close();
    }

    public void doRequest(String request) {
      String cmd = null;

      logmon.log(BasicLevel.DEBUG, getName() + ", request=" + request);

      try {
        // Tokenizes the request to parse it.
        StringTokenizer st = new StringTokenizer(request);

        cmd = st.nextToken();
        if (cmd.equals(STOP_SERVER)) {
          // Stop the AgentServer
          AgentServer.stop(false);
          logmon.log(BasicLevel.WARN, getName() + ", bye.");
        } else if (cmd.equals(CRASH_SERVER)) {
          // Kill the AgentServer
          logmon.log(BasicLevel.WARN, getName() + ", crash!");
          System.exit(0);
        } else if (cmd.equals(GC)) {
          Runtime runtime = Runtime.getRuntime();
          writer.println("before: " +
                         runtime.freeMemory() + " octets free / " +
                         runtime.totalMemory() + " octets.");
          runtime.gc();
          writer.println("after: " +
                         runtime.freeMemory() + " octets free / " +
                         runtime.totalMemory() + " octets.");
        } else if (cmd.equals(SET_VARIABLE)) {
          try {
            if (st.countTokens() != 2)
              throw new Exception("Usage: set property value");

            String property = st.nextToken();
            String value = st.nextToken();

            // finds variable class and name
            int pindex = property.lastIndexOf('.');
            if (pindex == -1) {
              // bad formed property name, ignores
              throw new Exception("bad formed property name: " + property);
            }
            String varClassName = property.substring(0, pindex);
            String varName = property.substring(pindex + 1);

            try {
              // finds variable
              Class varClass = Class.forName(varClassName);
              Field var = varClass.getDeclaredField(varName);
              // sets variable according to its type
              String varType = var.getType().getName();
              if (varType.equals("boolean") ||
                  varType.equals("java.lang.Boolean")) {
                var.set(null, new Boolean(value));
              } else if (varType.equals("int") ||
                  varType.equals("java.lang.Integer")) {
                var.set(null, new Integer(value));
              } else if (varType.equals("java.lang.String")) {
                var.set(null, value);
              } else {
                throw new Exception("error setting property " +
                                    varClassName + "." + varName +
                                    ": unexpected type " + varType);
              }
            } catch (Exception exc) {
              if (debug) exc.printStackTrace(writer);
              throw new Exception("error setting property " +
                                  varClassName + "." + varName +
                                  ": " + exc.getMessage());
            }
            writer.println("done.");
          } catch (Exception exc) {
            writer.println(exc.getMessage());
          }
        } else if (cmd.equals(GET_VARIABLE)) {
          try {
            if (st.countTokens() != 1)
              throw new Exception("Usage: get property");

            String property = st.nextToken();

            // finds variable class and name
            int pindex = property.lastIndexOf('.');
            if (pindex == -1) {
              // bad formed property name, ignores
              throw new Exception("bad formed property name: " + property);
            }
            String varClassName = property.substring(0, pindex);
            String varName = property.substring(pindex + 1);

            try {
              // finds variable
              Class varClass = Class.forName(varClassName);
              Field var = varClass.getDeclaredField(varName);
              // get the variable value
              Object value = var.get(null);
              writer.println(property + " = " + value);
            } catch (Exception exc) {
              if (debug) exc.printStackTrace(writer);
              throw new Exception("error getting property " +
                                  varClassName + "." + varName +
                                  ": " + exc.getMessage());
            }
          } catch (Exception exc) {
            writer.println(exc.getMessage());
          }
        } else if (cmd.equals(THREADS)) {
          String group = null;
          if (st.hasMoreTokens())
            group = st.nextToken();

          ThreadGroup tg = Thread.currentThread().getThreadGroup();
          while (tg.getParent() != null)
            tg = tg.getParent();
          int nbt = tg.activeCount();
          Thread[] tab = new Thread[nbt];
          tg.enumerate(tab);

          for (int j=0; j<nbt; j++) {
            if ((group != null) &&
                ! tab[j].getThreadGroup().getName().equals(group))
              continue;
            writer.println("+----------------------------------------");
            writer.println("[" +
                           ((group==null)?(tab[j].getThreadGroup().getName() + "."):"") +
                           tab[j].getName() + "]" +
                           (tab[j].isAlive()?" alive":"") +
                           (tab[j].isDaemon()?" daemon":"") + "\n " +
                           tab[j]);
          }
        } else if (cmd.equals(LIST_MCONS)) {
          for (Enumeration c=AgentServer.getConsumers();
          c.hasMoreElements(); ) {
            MessageConsumer cons = (MessageConsumer) c.nextElement();
            writer.println("+----------------------------------------");
            writer.println(cons);
          }
        } else if (cmd.equals(START_MCONS)) {
          String domain = null;
          if (st.hasMoreTokens()) {
            // start the identified consumer.
            domain = st.nextToken();
          }
          for (Enumeration c=AgentServer.getConsumers();
          c.hasMoreElements(); ) {
            MessageConsumer cons = (MessageConsumer) c.nextElement();

            if (((domain == null) || domain.equals(cons.getName()))) {
              try {
                cons.start();
                writer.println("start " + cons.getName() + " done.");
              } catch (Exception exc) {
                writer.println("Can't start "+ cons.getName() + ": " +
                               exc.getMessage());
                if (debug) exc.printStackTrace(writer);
              }
            }
          }
        } else if (cmd.equals(STOP_MCONS)) {
          String domain = null;
          if (st.hasMoreTokens()) {
            // stop the identified consumer.
            domain = st.nextToken();
          }
          for (Enumeration c=AgentServer.getConsumers();
          c.hasMoreElements(); ) {
            MessageConsumer cons = (MessageConsumer) c.nextElement();

            if (((domain == null) || domain.equals(cons.getName()))) {
              cons.stop();
              writer.println("stop " + cons.getName() + " done.");
            }
          }
        } else if (cmd.equals(LIST_SERVICE)) {
          ServiceDesc services[] = ServiceManager.getServices();
          for (int i=0; i<services.length; i++ ){
            writer.println("+----------------------------------------");
            writer.println(services[i].getClassName() + " (" +
                           services[i].getArguments() + ")" +
                           (services[i].isInitialized()?" initialized ":"") +
                           (services[i].isRunning()?" running":""));
          }
        } else if (cmd.equals(ADD_SERVICE)) {
          try {
            // Add a new Service
            String sclass = null;
            String args = null;
            try {
              sclass = st.nextToken();
              if (st.hasMoreTokens())
                args = st.nextToken();
            } catch (NoSuchElementException exc) {
              throw new Exception("Usage: add <sclass> [<args>]");
            }
            try {
              ServiceManager.register(sclass, args);
              writer.println("Service <" + sclass + "> registred.");
              ServiceManager.start(sclass);
              writer.println("Service <" + sclass + "> started.");
            } catch (Exception exc) {
              // Report the error
              writer.println("Can't start service: " + exc.getMessage());
              if (debug) exc.printStackTrace(writer);
            }
          } catch (Exception exc) {
            writer.println(exc.getMessage());
          }
        } else if (cmd.equals(REMOVE_SERVICE)) {
          // Remove an existing Service
          String sclass = null;
          try {
            sclass = st.nextToken();
          } catch (NoSuchElementException exc) {
            writer.println("Usage: " + REMOVE_SERVICE + " <sclass> [<args>]");
            return;
          }
          try {
            ServiceManager.stop(sclass);
            writer.println("Service <" + sclass + "> stopped.");
          } catch (Exception exc) {
            writer.println("Can't stop service: " + exc.getMessage());
            if (debug) exc.printStackTrace(writer);
          }
          try {
            ServiceManager.unregister(sclass);
            writer.println("Service <" + sclass + "> unregistred.");
          } catch (Exception exc) {
            writer.println("Can't unregister service: " + exc.getMessage());
            if (debug) exc.printStackTrace(writer);
          }
        } else if (cmd.equals(DUMP)) {
          AgentId id = null;
          try {
            id = AgentId.fromString(st.nextToken());
          } catch (IllegalArgumentException exc) {
            writer.println("Usage: " + DUMP + " #x.y.z");
            return;
          }
          try {
            writer.println(AgentServer.getEngine().dumpAgent(id));
          } catch (Exception exc) {
            writer.println("Can't launch server: " + exc.getMessage());
            if (debug) exc.printStackTrace(writer);
          }
        } else if (cmd.equals(NONE)) {
        } else if (cmd.equals(PING)) {
          writer.println(AgentServer.getServerId());
        } else if (cmd.equals(CONFIG)) {
          try {
            A3CMLConfig a3CMLConfig = AgentServer.getConfig();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PrintWriter out = new PrintWriter(baos);
            A3CML.toXML(a3CMLConfig, out);
            out.flush();
            baos.flush();
            baos.close();
            byte[] bytes = baos.toByteArray();
            writer.println(new String(bytes));
          } catch (Exception exc) {
            writer.println("Can't load configuration: " + exc.getMessage());
            if (debug) exc.printStackTrace(writer);
          }
        } else if (cmd.equals(LOG)){
          PrintStream oldErr = System.err;
          try {
            System.setErr(new PrintStream(socket.getOutputStream()));
            String topic = st.nextToken();
            String level = st.nextToken();
            int intLevel;
            if (level.equals("DEBUG")) {
              intLevel = org.objectweb.util.monolog.api.BasicLevel.DEBUG;
            } else if (level.equals("ERROR")) {
              intLevel = org.objectweb.util.monolog.api.BasicLevel.ERROR;
            } else if (level.equals("FATAL")) {
              intLevel = org.objectweb.util.monolog.api.BasicLevel.FATAL;
            } else if (level.equals("INFO")) {
              intLevel = org.objectweb.util.monolog.api.BasicLevel.INFO;
            } else if (level.equals("INHERIT")) {
              intLevel = org.objectweb.util.monolog.api.BasicLevel.INHERIT;
            } else if (level.equals("WARN")) {
              intLevel = org.objectweb.util.monolog.api.BasicLevel.WARN;
            } else {
              writer.println("Unknown level: " + level);
              return;
            }
            Debug.setLoggerLevel(topic, intLevel);
          } catch(Exception exc){
            writer.println(exc.getMessage());
          } finally{
            System.setErr(oldErr);
            writer.println("OK");
          }
        } else if (cmd.equals(HELP)) {
          writer.println(
                         "Description of available commands:\n" +
                         "\t" + HELP +
                         "\n\t\tGives the summary of the options.\n" +
                         "\t" + STOP_SERVER +
                         "\n\t\tStops the server.\n" +
                         "\t" + SET_VARIABLE + "variable value" +
                         "\n\t\tSet the specified static variable with the given value.\n" +
                         "\t" + GET_VARIABLE +
                         "\n\t\tReturn the value of the specified static variable.\n" +
                         "\t" + GC +
                         "\n\t\tRun the garbage collector in the specified A3 server.\n" +
                         "\t" + THREADS + " [group]" +
                         "\n\t\tList all threads in server JVM.\n" +
                         "\t" + LIST_MCONS +
                         "\n\t\tList all defined consumers.\n" +
                         "\t" + START_MCONS + " [domain]" +
                         "\n\t\tStarts the specified MessageConsumer.\n" +
                         "\t" + STOP_MCONS + " [domain]" +
                         "\n\t\tStops the specified MessageConsumer.\n" +
                         "\t" + LIST_SERVICE +
                         "\n\t\tList all registered services.\n" +
                         "\t" + ADD_SERVICE + " classname arguments" +
                         "\n\t\tRegisters and starts the specified Service.\n" +
                         "\t" + REMOVE_SERVICE + " classname" +
                         "\n\t\tStops then unregister the specified Service.\n" +
                         "\t" + CONFIG +
          "\n\t\tReturns the configuration of the server in XML format.\n");
        } else {
          writer.println("unknown command:" + cmd);
        }
      } finally {
      }
    }
  }
}
TOP

Related Classes of fr.dyade.aaa.agent.AdminProxy

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.
nalytics.com/analytics.js','ga'); ga('create', 'UA-20639858-1', 'auto'); ga('send', 'pageview');