/*
 * JBoss, Home of Professional Open Source
 * Copyright 2003-2011, Red Hat, Inc. and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This 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 (at your option) any later version.
 *
 * This software 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 software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.mobicents.slee.container.management.console.server.mbeans;

import java.util.List;
import java.util.logging.Level;

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;

import org.mobicents.slee.container.management.console.client.ManagementConsoleException;

/**
 * @author baranowb
 *
 */
public class LogManagementMBeanUtils {

  private MBeanServerConnection mbeanServer = null;

  private ObjectName logMgmtMBeanName = null;

  public LogManagementMBeanUtils(MBeanServerConnection mbeanServer, ObjectName sleeManagementMBean) throws ManagementConsoleException {
    super();
    this.mbeanServer = mbeanServer;
    try {
      logMgmtMBeanName = new ObjectName("org.mobicents.slee:name=LogManagementMBean");
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  public void _setDefaultLoggerLevel(Level l) throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "_setDefaultLoggerLevel", new Object[] { l }, new String[] { "java.util.logging.Level" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }

  }

  public Level _getDefaultLoggerLevel() throws ManagementConsoleException {
    try {
      return (Level) this.mbeanServer.invoke(logMgmtMBeanName, "_getDefaultLoggerLevel", null, null);
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  public void setDefaultLoggerLevel(String l) throws ManagementConsoleException {
    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "setDefaultLoggerLevel", new Object[] { l }, new String[] { "java.lang.String" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  public String getDefaultLoggerLevel() throws ManagementConsoleException {
    try {
      return (String) this.mbeanServer.invoke(logMgmtMBeanName, "getDefaultLoggerLevel", null, null);
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  public void _setDefaultHandlerLevel(Level l) throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "_setDefaultHandlerLevel", new Object[] { l }, new String[] { "java.util.logging.Level" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }

  }

  public Level _getDefaultHandlerLevel() throws ManagementConsoleException {
    try {
      return (Level) this.mbeanServer.invoke(logMgmtMBeanName, "_getDefaultHandlerLevel", null, null);
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  public void setDefaultHandlerLevel(String l) throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "setDefaultHandlerLevel", new Object[] { l }, new String[] { "java.lang.String" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  public String getDefaultHandlerLevel() throws ManagementConsoleException {
    try {
      return (String) this.mbeanServer.invoke(logMgmtMBeanName, "getDefaultHandlerLevel", null, null);
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  public void setDefaultNotificationInterval(int numberOfEntries) throws ManagementConsoleException {
    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "setDefaultNotificationInterval", new Object[] { numberOfEntries }, new String[] { "int" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  public int getDefaultNotificationInterval() throws ManagementConsoleException {
    try {
      return ((Integer) this.mbeanServer.invoke(logMgmtMBeanName, "getDefaultNotificationInterval", null, null)).intValue();
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  // ========= END PROPS

  /**
   * SImilar to LoggingMXBean, return list of available loggers. Filter is string that has to occur in loggers name.
   *
   * @param - specifies string that has to occur in loggers name, if null - all names are returned. (Simply regex)
   * @return
   */
  public List<String> getLoggerNames(String regex) throws ManagementConsoleException {
    try {
      return (List<String>) this.mbeanServer.invoke(logMgmtMBeanName, "getLoggerNames", new Object[] { regex }, new String[] { "java.lang.String" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  /**
   * Same as LoggingMXBean - sets level for certain logger.
   *
   * @param loggerName
   *          - name of the logger
   * @param level
   *          - level to be set
   * @throws IllegalArgumentException
   *           - thrown when there is no logger under certain name.
   */
  public void setLoggerLevel(String loggerName, Level level) throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "setLoggerLevel", new Object[] { loggerName, level }, new String[] { "java.lang.String",
          "java.util.logging.Level" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }

  }

  /**
   * Same as LoggingMXBean - sets level for certain logger. This method accepts String representation of logger level.
   *
   * @param loggerName
   *          - name of the logger
   * @param level
   *          - level to be set
   * @throws IllegalArgumentException
   *           - thrown when there is no logger under certain name or String dose not represent valid logger level.
   */
  public void setLoggerLevel(String loggerName, String level) throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "setLoggerLevel", new Object[] { loggerName, level }, new String[] { "java.lang.String", "java.lang.String" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  /**
   * Resets all loggers level to default one
   */
  public void resetLoggerLevels() throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "resetLoggerLevels", null, null);
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }

  }

  /**
   * Resets loggers under certain name to log on certain level.
   *
   * @param loggerName
   */
  public void resetLoggerLevel(String loggerName) throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "resetLoggerLevel", new Object[] { loggerName }, new String[] { "java.lang.String" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  /**
   * Removes(set level to Level.OFF, handlers are removed) all loggers that were created by this MBean - this will usually include loggers
   * for whole packages. It also removes all handlers - either NotificationHandler and SocketHandler for each defined logger(either by this
   * MBean or by source code).
   */
  public void clearLoggers() throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "clearLoggers", null, null);
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  /**
   * Removes all loggers under certain branch.
   *
   * @param name
   *          - logger name(branch name)
   */
  public void clearLoggers(String name) throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "clearLoggers", new Object[] { name }, new String[] { "java.lang.String" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }

  }

  /**
   * Tries to add logger if it doesnt exist
   *
   * @param name
   *          - name of logger
   * @param level
   *          - level for this logger, if null than default level for logger is used
   * @return

   *
true - if logger didnt exist and it was created

   *
false - if logger did exist and it was not created

   *

   * @throws NullPointerException
   *           - when arg is null{}
   */
  public boolean addLogger(String name, Level level) throws NullPointerException, ManagementConsoleException {
    try {
      return ((Boolean) this.mbeanServer.invoke(logMgmtMBeanName, "addLogger", new Object[] { name, level }, new String[] { "java.lang.String",
          "java.util.logging.Level" })).booleanValue();
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  /**
   * Tries to add logger if it doesnt exist
   *
   * @param name
   *          - name of logger
   * @param level
   *          - level for this logger, if null than default level for logger is used
   * @return

   *
true - if logger didnt exist and it was created

   *
false - if logger did exist and it was not created

   *

   *
   * @throws IllegalArgumentException
   *           - when level is not valid string representation of logging level
   * @throws NullPointerException
   *           - when arg is null{}
   */
  public boolean addLogger(String name, String level) throws ManagementConsoleException {
    try {
      return ((Boolean) this.mbeanServer.invoke(logMgmtMBeanName, "addLogger", new Object[] { name, level }, new String[] { "java.lang.String",
          "java.lang.String" })).booleanValue();
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  /**
   * Adds SocketHandler to certain logger, this logger must exist prior this function is called
   *
   * @param loggerName
   *          - name of the logger, cant be null
   * @param handlerLevel
   *          - level for this handler, if its null default level for handlers will be used
   * @param handlerName
   *          - name for this handler, cant be duplicate.
   * @param formaterClassName
   *          - name of formater class for this handler, can be null.
   * @param filterClassName
   *          - name of filter class for this handler, can be null.
   * @param host
   *          - host address
   * @param port
   *          - port address
   * @throws IllegalArgumentException
   *           - thrown when:
   *

   *
host is not a valid inet address

   *
port <0

   *

   * @throws NullPointerException
   *           - if arg other than:
   *

   *
formaterClassName

   *
filterClassName

   *
handlerLevel

   *

   *           is null.
   * @throws IllegalStateException
   *           :- thrown when:
   *

   *
Logger under certain name doesnt exist

   *
handler name is duplicate of another handler for this logger or is reserved one ->NOTIFICATION

   *

   * @throw IOException - when host cant be reached
   */
  public void addSocketHandler(String loggerName, Level handlerLevel, String handlerName, String formaterClassName, String filterClassName, String host,
      int port) throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "addSocketHandler", new Object[] { loggerName, handlerLevel, handlerName, formaterClassName, filterClassName,
          host, port }, new String[] { "java.lang.String", "java.util.logging.Level", "java.lang.String", "java.lang.String", "java.lang.String",
          "java.lang.String", "int" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }

  }

  /**
   * Adds SocketHandler to certain logger, this logger must exist prior this function is called
   *
   * @param loggerName
   *          - name of the logger, cant be null
   * @param handlerLevel
   *          - level for this handler, if its null default level for handlers will be used
   * @param handlerName
   *          - name for this handler, cant be duplicate.
   * @param formaterClassName
   *          - name of formater class for this handler, can be null.
   * @param filterClassName
   *          - name of filter class for this handler, can be null.
   * @param host
   *          - host address
   * @param port
   *          - port address
   * @throws IllegalArgumentException
   *           - thrown when:
   *

   *
host is not a valid inet address

   *
port <0

   *
handlerLevel!=null and does not represent valid logging level

   *
formaterClassName is not valid formater class

   *
filterClassName is not valid filter class

   *

   * @throws NullPointerException
   *           - if arg other than:
   *

   *
formaterClassName

   *
filterClassName

   *
handlerLevel

   *

   *           is null.
   * @throws IllegalStateException
   *           :- thrown when:
   *

   *
Logger under certain name doesnt exist

   *
handler name is duplicate of another handler for this logger or is reserved one ->NOTIFICATION

   *

   * @throw IOException - when host cant be reached
   */
  public void addSocketHandler(String loggerName, String handlerLevel, String handlerName, String formaterClassName, String filterClassName, String host,
      int port) throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "addSocketHandler", new Object[] { loggerName, handlerLevel, handlerName, formaterClassName, filterClassName,
          host, port }, new String[] { "java.lang.String", "java.lang.String", "java.lang.String", "java.lang.String", "java.lang.String", "java.lang.String",
          "int" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  /**
   * Tries to remove handler from logger.
   *
   * @param loggerName
   *          - name of the logger
   * @param handlerName
   *          - handler name that has been added by this MBean
   * @return

   *
true - if logger exists, and it was removed

   *
false - otherwise

   *

   */
  public boolean removeHandler(String loggerName, String handlerName) throws ManagementConsoleException {
    try {
      return ((Boolean) this.mbeanServer.invoke(logMgmtMBeanName, "removeHandler", new Object[] { loggerName, handlerName }, new String[] { "java.lang.String",
          "java.lang.String" })).booleanValue();
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  public boolean removeHandler(String loggerName, int index) throws ManagementConsoleException {
    try {
      return ((Boolean) this.mbeanServer.invoke(logMgmtMBeanName, "removeHandler", new Object[] { loggerName, index },
          new String[] { "java.lang.String", "int" })).booleanValue();
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  /**
   * Adds notification handler to logger if it exists. Its name is set to NOTIFICATION. There can be only one notification handler.
   * This handler holds reference to up to numberOfEntries log entries and fires notification. Notification can be triggered prematurely in
   * case when someone calls fetchLogContent function, this will cause notification to be fired along with log entries return as outcome of
   * invocation.
   *
   * @param loggerName
   *          - name of the logger, it must exists prior this function call
   * @param numberOfEntries
   *          - number of log entries after notification is sent. If <=0 default value is used
   * @param level
   *          - level for this handler, if null, default value is used
   * @param formaterClassName
   *          - name of formater class for this handler, can be null.
   * @param filterClassName
   *          - name of filter class for this handler, can be null.
   * @throws IllegalArgumentException
   *           thrown when:
   *

   *
logger under certain name does not exist

   *
formaterClassName is not valid formater class

   *
filterClassName is not valid filter class

   *

   * @throws IllegalStateException
   *           - logger under that name already has notification handler
   * @throws NullPointerException
   *           - loggerName is null
   */
  public void addNotificationHandler(String loggerName, int numberOfEntries, Level level, String formaterClassName, String filterClassName)
      throws IllegalArgumentException, IllegalStateException, NullPointerException, ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "addNotificationHandler",
          new Object[] { loggerName, numberOfEntries, level, formaterClassName, filterClassName }, new String[] { "java.lang.String", "int",
              "java.util.logging.Logger", "java.lang.String", "java.lang.String" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }

  }

  public void addNotificationHandler(String loggerName, int numberOfEntries, String level, String formaterClassName, String filterClassName)
      throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "addNotificationHandler",
          new Object[] { loggerName, numberOfEntries, level, formaterClassName, filterClassName }, new String[] { "java.lang.String", "int",
              "java.lang.String", "java.lang.String", "java.lang.String" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }

  }

  /**
   * Returns names of handlers for logger
   *
   * @param loggerName
   *          - logger name, cant be null, must be valid
   * @return List with names of handlers for this loggers
   * @throws IllegalArgumentException
   *           - logger does not exist
   */
  public List getHandlerNamesForLogger(String loggerName) throws ManagementConsoleException {
    try {
      return (List) this.mbeanServer.invoke(logMgmtMBeanName, "getHandlerNamesForLogger", new Object[] { loggerName }, new String[] { "java.lang.String" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  /**
   * Fetches level of particular handler
   *
   * @param loggerName
   *          - name of the logger, cant be null and logger must exist
   * @param handlerName
   *          - valid name of handler, cant be null
   * @return
   * @throws IllegalArgumentException
   *           thrown when:
   *

   *
handler does not exist

   *

   *
   * @throws NullPointerException
   *           thrown when:
   *

   *
arg is null

   *

   */
  public String getHandlerLevel(String loggerName, String handlerName) throws ManagementConsoleException {
    try {
      return (String) this.mbeanServer.invoke(logMgmtMBeanName, "getHandlerLevel", new Object[] { loggerName, handlerName }, new String[] { "java.lang.String",
          "java.lang.String" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  /**
   *
   * @param loggerName
   *          - name of the logger, cant be null and logger must exist
   * @param handlerName
   *          - name of the handler, cant be null and handler ust exist
   * @return
   * @throws IllegalArgumentException
   *           thrown when:
   *

   *
logger does not exist

   *
handler under specific name does not exist

   *

   * @throws NullPointerException
   *           thrown when:
   *

   *
arg is null

   *

   */
  public String getHandlerFilterClassName(String loggerName, String handlerName) throws IllegalArgumentException, NullPointerException,
      ManagementConsoleException {
    try {
      return (String) this.mbeanServer.invoke(logMgmtMBeanName, "getHandlerFilterClassName", new Object[] { loggerName, handlerName }, new String[] {
          "java.lang.String", "java.lang.String" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  /**
   *
   * @param loggerName
   *          - name of the logger, cant be null and logger must exist
   * @param handlerName
   *          - name of the handler, cant be null and handler ust exist
   * @return
   * @throws IllegalArgumentException
   *           thrown when:
   *

   *
logger does not exist

   *
handler under specific name does not exist

   *

   * @throws NullPointerException
   *           thrown when:
   *

   *
arg is null

   *

   */
  public String getHandlerFormaterClassName(String loggerName, String handlerName) throws IllegalArgumentException, NullPointerException,
      ManagementConsoleException {
    try {
      return (String) this.mbeanServer.invoke(logMgmtMBeanName, "getHandlerFormaterClassName", new Object[] { loggerName, handlerName }, new String[] {
          "java.lang.String", "java.lang.String" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  /**
   *
   * @param loggerName
   *          - name of the logger, cant be null and logger must exist
   * @return
   * @throws IllegalArgumentException
   *           thrown when:
   *

   *
logger does not exist

   *

   * @throws NullPointerException
   *           thrown when:
   *

   *
args is null

   * @throws IllegalStateException
   *           thrown when:
   *

   *
logger does not have notification handler

   *

   */
  public int getHandlerNotificationInterval(String loggerName) throws ManagementConsoleException {
    try {
      return ((Integer) this.mbeanServer.invoke(logMgmtMBeanName, "getHandlerNotificationInterval", new Object[] { loggerName },
          new String[] { "java.lang.String" })).intValue();
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  public String getHandlerClassName(String loggerName, String handlerName) throws IllegalArgumentException, NullPointerException, IllegalStateException,
      ManagementConsoleException {
    try {
      return (String) this.mbeanServer.invoke(logMgmtMBeanName, "getHandlerClassName", new Object[] { loggerName, handlerName }, new String[] {
          "java.lang.String", "java.lang.String" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  public String getHandlerClassName(String loggerName, int index) throws IllegalArgumentException, NullPointerException, IllegalStateException,
      ManagementConsoleException {
    try {
      return (String) this.mbeanServer.invoke(logMgmtMBeanName, "getHandlerClassName", new Object[] { loggerName, index }, new String[] { "java.lang.String",
          "int" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  /**
   * Fetches level of particular handler
   *
   * @param loggerName
   *          - name of the logger, cant be null and logger must exist
   * @param handlerName
   *          - valid name of handler, cant be null
   * @param level
   *          - new handelr level
   * @return
   * @throws IllegalArgumentException
   *           thrown when:
   *

   *
handler does not exist

   *
logger does not exist

   *
level is not valid string representation of logging level

   *

   *
   * @throws NullPointerException
   *           thrown when:
   *

   *
arg is null

   *

   */
  public void setHandlerLevel(String loggerName, String handlerName, String level) throws IllegalArgumentException, NullPointerException,
      ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "setHandlerLevel", new Object[] { loggerName, handlerName, level }, new String[] { "java.lang.String",
          "java.lang.String", "java.lang.String" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }

  }

  /**
   * Fetches level of particular handler
   *
   * @param loggerName
   *          - name of the logger, cant be null and logger must exist
   * @param handlerName
   *          - valid name of handler, cant be null
   * @param level
   *          - new handelr level
   * @return
   * @throws IllegalArgumentException
   *           thrown when:
   *

   *
handler does not exist

   *
logger does not exist

   *

   *
   * @throws NullPointerException
   *           thrown when:
   *

   *
arg is null

   *

   */
  public void setHandlerLevel(String loggerName, String handlerName, Level level) throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "setHandlerLevel", new Object[] { loggerName, handlerName, level }, new String[] { "java.lang.String",
          "java.lang.String", "java.util.logging.Level" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }

  }

  /**
   *
   * @param loggerName
   *          - name of the logger, cant be null and logger must exist
   * @param handlerName
   *          - name of the handler, cant be null and handler ust exist
   * @return
   * @throws IllegalArgumentException
   *           thrown when:
   *

   *
logger does not exist

   *
handler under specific name does not exist

   *
className is not valid filter class name

   *

   * @throws NullPointerException
   *           thrown when:
   *

   *
args is null

   *

   */
  public void setHandlerFilterClassName(String loggerName, String handlerName, String className) throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "setHandlerFilterClassName", new Object[] { loggerName, handlerName, className }, new String[] {
          "java.lang.String", "java.lang.String", "java.lang.String" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }

  }

  /**
   *
   * @param loggerName
   *          - name of the logger, cant be null and logger must exist
   * @param handlerName
   *          - name of the handler, cant be null and handler ust exist
   * @return
   * @throws IllegalArgumentException
   *           thrown when:
   *

   *
logger does not exist

   *
handler under specific name does not exist

   *
className is not a valid formater class name

   *

   * @throws NullPointerException
   *           thrown when:
   *

   *
args is null

   *

   */
  public void setHandlerFormaterClassName(String loggerName, String handlerName, String className) throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "setHandlerFormaterClassName", new Object[] { loggerName, handlerName, className }, new String[] {
          "java.lang.String", "java.lang.String", "java.lang.String" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }

  }

  /**
   *
   * @param loggerName
   *          - name of the logger, cant be null and logger must exist
   * @return
   * @throws IllegalArgumentException
   *           thrown when:
   *

   *
logger does not exist

   *

   * @throws NullPointerException
   *           thrown when:
   *

   *
args is null

   * @throws IllegalStateException
   *           thrown when:
   *

   *
logger does not have notification handler

   *

   */
  public void setHandlerNotificationInterval(String loggerName, int numberOfEntries) throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "setHandlerNotificationInterval", new Object[] { loggerName, numberOfEntries }, new String[] {
          "java.lang.String", "int" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }

  }

  /**
   *
   * @param loggerName
   *          - name of the logger, cant be null and logger must exist
   * @throws IllegalArgumentException
   *           thrown when:
   *

   *
logger does not exist

   *

   * @throws NullPointerException
   *           thrown when:
   *

   *
args is null

   * @throws IllegalStateException
   *           thrown when:
   *

   *
logger does not have notification handler

   *

   */
  public String fetchLog(String loggerName) throws ManagementConsoleException {
    try {
      return (String) this.mbeanServer.invoke(logMgmtMBeanName, "fetchLog", new Object[] { loggerName }, new String[] { "java.lang.String" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  // ** METHODS BELOW ARE GENERIC, THEY ALLOW TO CONTROLL ALL HANDLERS
  /**
   * Triggers reareadigng configuration file.
   *
   * @param uri
   *          - target configuration file in Properties format, if null, local file is read(jre local)
   */
  public void reReadConf(String uri) throws ManagementConsoleException {

  }

  public void addHandler(String loggerName, String handlerName, String handlerClassName, String formaterClass, String filterClass,
      String[] constructorParameters, String[] paramValues) throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "addHandler", new Object[] { loggerName, handlerName, handlerClassName, formaterClass, filterClass,
          constructorParameters, paramValues }, new String[] { "java.lang.String", "java.lang.String", "java.lang.String", "java.lang.String",
          "java.lang.String", "java.lang.String[]", "java.lang.String[]", });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }

  }

  public int numberOfHandlers(String loggerName) throws ManagementConsoleException {
    try {
      return ((Integer) this.mbeanServer.invoke(logMgmtMBeanName, "numberOfHandlers", new Object[] { loggerName }, new String[] { "java.lang.String" }))
          .intValue();
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  public String getGenericHandlerLevel(String loggerName, int index) throws ManagementConsoleException {
    try {
      return ((String) this.mbeanServer.invoke(logMgmtMBeanName, "getGenericHandlerLevel", new Object[] { loggerName, index }, new String[] {
          "java.lang.String", "int" }));
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  public String getGenericHandlerFilterClassName(String loggerName, int index) throws NullPointerException, IllegalArgumentException,
      ManagementConsoleException {
    try {
      return ((String) this.mbeanServer.invoke(logMgmtMBeanName, "getGenericHandlerFilterClassName", new Object[] { loggerName, index }, new String[] {
          "java.lang.String", "int" }));
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  public String getGenericHandlerFormatterClassName(String loggerName, int index) throws ManagementConsoleException {
    try {
      return ((String) this.mbeanServer.invoke(logMgmtMBeanName, "getGenericHandlerFormatterClassName", new Object[] { loggerName, index }, new String[] {
          "java.lang.String", "int" }));
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  public void setGenericHandlerLevel(String loggerName, int index, String level) throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "setGenericHandlerLevel", new Object[] { loggerName, index, level }, new String[] { "java.lang.String", "int",
          "java.lang.String" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }

  }

  public void setGenericHandlerFilterClassName(String loggerName, int index, String className) throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "setGenericHandlerFilterClassName", new Object[] { loggerName, index, className }, new String[] {
          "java.lang.String", "int", "java.lang.String" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }

  }

  public void setGenericHandlerFormatterClassName(String loggerName, int index, String className) throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "setGenericHandlerFormatterClassName", new Object[] { loggerName, index, className }, new String[] {
          "java.lang.String", "int", "java.lang.String" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }

  }

  public String getHandlerName(String loggerName, int index) throws ManagementConsoleException {
    try {
      return (String) this.mbeanServer.invoke(logMgmtMBeanName, "getHandlerName", new Object[] { loggerName, index },
          new String[] { "java.lang.String", "int" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  public void setHandlerName(String loggerName, int index, String newName) throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "setHandlerName", new Object[] { loggerName, index, newName }, new String[] { "java.lang.String", "int",
          "java.lang.String" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }

  }

  public void setUseParentHandlersFlag(String loggerName, boolean flag) throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "setUseParentHandlersFlag", new Object[] { loggerName, flag }, new String[] { "java.lang.String", "boolean" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }

  }

  public boolean getUseParentHandlersFlag(String loggerName) throws ManagementConsoleException {
    try {
      return ((Boolean) this.mbeanServer.invoke(logMgmtMBeanName, "getUseParentHandlersFlag", new Object[] { loggerName }, new String[] { "java.lang.String" }))
          .booleanValue();
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }

  }

  public String getLoggerLevel(String loggerName) throws ManagementConsoleException {
    try {
      return ((String) this.mbeanServer.invoke(logMgmtMBeanName, "getLoggerLevel", new Object[] { loggerName }, new String[] { "java.lang.String" }));
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  public void setLoggerFilterClassName(String loggerName, String className, String[] constructorParameters, String[] paramValues)
      throws ManagementConsoleException {

    try {
      this.mbeanServer.invoke(logMgmtMBeanName, "getLoggerFilterClassName", new Object[] { loggerName, className, constructorParameters, paramValues },
          new String[] { "java.lang.String", "java.lang.String", "java.lang.String[]", "java.lang.String[]" });
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

  public String getLoggerFilterClassName(String loggerName) throws ManagementConsoleException {
    try {
      return ((String) this.mbeanServer.invoke(logMgmtMBeanName, "getLoggerFilterClassName", new Object[] { loggerName }, new String[] { "java.lang.String" }));
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new ManagementConsoleException(SleeManagementMBeanUtils.doMessage(e));
    }
  }

}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2003-2011, Red Hat, Inc. and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This 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 (at your option) any later version.
 *
 * This software 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 software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.mobicents.slee.container.management.console.client.log;

import org.mobicents.slee.container.management.console.client.ServerConnection;
import org.mobicents.slee.container.management.console.client.common.CommonControl;
import org.mobicents.slee.container.management.console.client.common.ListPanel;
import org.mobicents.slee.container.management.console.client.common.UserInterface;

import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

/**
 * This component allows user to perform some operations - setting defualt handler/logger level, readingCFG, reseting/clearing loggers. It
 * also
 *
 * @author baranowb
 *
 */
public class DefaultOperationsPanel extends Composite implements CommonControl {

  private ListBox _defaultHandlerLevel = new ListBox();

  private ListBox _defaultLoggerLevel = new ListBox();

  private TextBox _resetLoggerList = new TextBox();

  private TextBox _clearLoggerList = new TextBox();

  private TextBox _defaultNotificationInterval = new TextBox();

  private TextBox _newLoggerName = new TextBox();
  protected TextBox _readUri = new TextBox();
  private static final String _ll_Explanation = "Sets default logger level - this is used when no level is specified, loggers are being reset or create via tree.";
  private static final String _hl_Explanation = "Sets default handler level - this is used when no level is specified and handler is beeing created";
  private static final String _cfg_Explanation = "Reads java.util.logging properties file in order to configure loggers, requires URI - can be left empty";
  private static final String _cclear_Explanation = "Set logger levels to OFF, removes all handlers. Requires regex to match logger names or empty to match restcomm domain.";
  private static final String _reset_Explanation = "Resets logger levels to current default value. Requires regex to match logger names or empty to match restcomm domain.";
  private static final String _add_Logger_Explanation = "Adds new logger specified by passed FQDN.";
  private DockPanel display = new DockPanel();

  private LogStructureTreePanel logStructureTreePanel = null;

  public DefaultOperationsPanel(LogStructureTreePanel logStructureTreePanel) {
    super();
    this.logStructureTreePanel = logStructureTreePanel;
    for (int i = 0; i < LogTreeNode._LEVELS.length; i++) {
      _defaultHandlerLevel.addItem(LogTreeNode._LEVELS[i], LogTreeNode._LEVELS[i]);
      _defaultLoggerLevel.addItem(LogTreeNode._LEVELS[i], LogTreeNode._LEVELS[i]);
    }
    initWidget(display);

  }

  public void onHide() {
    this.display.clear();

  }

  /*
   * (non-Javadoc)
   *
   * @see org.mobicents.slee.container.management.console.client.common.CommonControl #onInit()
   */
  public void onInit() {
    // TODO Auto-generated method stub

  }

  /*
   * (non-Javadoc)
   *
   * @see org.mobicents.slee.container.management.console.client.common.CommonControl #onShow()
   */
  public void onShow() {

    ListPanel operations = new ListPanel();
    operations.setWidth("100%");
    this.display.setHorizontalAlignment(DockPanel.ALIGN_CENTER);
    this.display.setVerticalAlignment(DockPanel.ALIGN_TOP);
    this.display.add(operations, DockPanel.CENTER);
    this.display.setCellHeight(operations, "100%");
    this.display.setCellWidth(operations, "100%");

    operations.setHeader(0, "Operation name");
    operations.setHeader(1, "Parameters");
    operations.setHeader(2, "Operation trigger");
    // operations.setHeader(3, "Operation detials");

    operations.setColumnWidth(0, "33%");
    operations.setColumnWidth(1, "33%");
    operations.setColumnWidth(2, "33%");
    // operations.setColumnWidth(3, "55%");

    // Operations
    // Set degault logger level
    operations.setCellText(1, 0, "Default logger level");
    operations.setCell(1, 1, null);
    operations.setCell(1, 2, _defaultLoggerLevel);
    // operations.setCellText(1, 3, _ll_Explanation);

    _defaultLoggerLevel.setTitle(_ll_Explanation);

    // Set default handler level
    operations.setCellText(2, 0, "Default handler level");
    operations.setCell(2, 1, null);
    operations.setCell(2, 2, _defaultHandlerLevel);
    // operations.setCell(2, 3, new Label(_hl_Explanation,true));
    _defaultHandlerLevel.setTitle(_hl_Explanation);

    // read cfg

    Hyperlink readLink = new Hyperlink("Trigger", null);
    // final TextBox uri=new TextBox();
    operations.setCellText(3, 0, "Read logger cfg");
    operations.setCell(3, 1, _readUri);
    operations.setCell(3, 2, readLink);
    // operations.setCellText(3, 3, _cfg_Explanation);
    readLink.setTitle(_cfg_Explanation);

    // reset loggers
    Hyperlink resetLink = new Hyperlink("Trigger", null);
    // final TextBox resetRegex=new TextBox();
    operations.setCellText(4, 0, "Reset loggers level");
    operations.setCell(4, 1, _resetLoggerList);
    operations.setCell(4, 2, resetLink);
    resetLink.setTitle(_reset_Explanation);

    // clear loggers loggers
    Hyperlink clearLink = new Hyperlink("Trigger", null);
    // final TextBox clearRegex=new TextBox();
    operations.setCellText(5, 0, "Turns off loggers");
    operations.setCell(5, 1, _clearLoggerList);
    operations.setCell(5, 2, clearLink);
    clearLink.setTitle(_cclear_Explanation);

    // clear loggers loggers
    Hyperlink addLogger = new Hyperlink("Trigger", null);
    // final TextBox clearRegex = new TextBox();
    operations.setCellText(6, 0, "Add logger");
    operations.setCell(6, 1, _newLoggerName);
    operations.setCell(6, 2, addLogger);
    addLogger.setTitle(_add_Logger_Explanation);

    Hyperlink setInterval = new Hyperlink("Trigger", null);
    // final TextBox clearRegex = new TextBox();
    operations.setCellText(7, 0, "Default notification");
    operations.setCell(7, 1, _defaultNotificationInterval);
    operations.setCell(7, 2, setInterval);
    // clearLink.setTitle(_add_Logger_Explanation);

    // Click listeners
    _defaultLoggerLevel.addClickListener(new ClickListener() {

      public void onClick(Widget arg0) {
        ServerConnection.logServiceAsync.setDefaultLoggerLevel(_defaultLoggerLevel.getItemText(_defaultLoggerLevel.getSelectedIndex()), new AsyncCallback() {

          public void onFailure(Throwable t) {
            UserInterface.getLogPanel().error("Failed to set value due to:" + t.getMessage());

          }

          public void onSuccess(Object arg0) {
            // TODO Auto-generated method stub

          }
        });

      }
    });

    _defaultHandlerLevel.addClickListener(new ClickListener() {

      public void onClick(Widget arg0) {
        ServerConnection.logServiceAsync.setDefaultHandlerLevel(_defaultHandlerLevel.getItemText(_defaultHandlerLevel.getSelectedIndex()), new AsyncCallback() {

          public void onFailure(Throwable t) {
            UserInterface.getLogPanel().error("Failed to set value due to:" + t.getMessage());

          }

          public void onSuccess(Object arg0) {
            // TODO Auto-generated method stub

          }
        });

      }
    });

    readLink.addClickListener(new ClickListener() {

      public void onClick(Widget arg0) {
        ServerConnection.logServiceAsync.reReadConf(_readUri.getText(), new AsyncCallback() {

          public void onFailure(Throwable t) {
            UserInterface.getLogPanel().error("Failed to set value due to:" + t.getMessage());

          }

          public void onSuccess(Object arg0) {
            logStructureTreePanel.refreshData();

          }
        });

      }
    });
    resetLink.addClickListener(new ClickListener() {

      public void onClick(Widget arg0) {
        ServerConnection.logServiceAsync.resetLoggerLevel(_resetLoggerList.getText(), new AsyncCallback() {

          public void onFailure(Throwable t) {
            UserInterface.getLogPanel().error("Failed to set value due to:" + t.getMessage());

          }

          public void onSuccess(Object arg0) {
            logStructureTreePanel.refreshData();

          }
        });

      }
    });

    clearLink.addClickListener(new ClickListener() {

      public void onClick(Widget arg0) {
        ServerConnection.logServiceAsync.clearLoggers(_clearLoggerList.getText(), new AsyncCallback() {

          public void onFailure(Throwable t) {
            UserInterface.getLogPanel().error("Failed to set value due to:" + t.getMessage());

          }

          public void onSuccess(Object arg0) {
            logStructureTreePanel.refreshData();

          }
        });

      }
    });

    addLogger.addClickListener(new ClickListener() {

      public void onClick(Widget arg0) {
        ServerConnection.logServiceAsync.addLogger(_newLoggerName.getText(), _defaultLoggerLevel.getItemText(_defaultLoggerLevel.getSelectedIndex()),
            new AsyncCallback() {

              public void onFailure(Throwable t) {
                UserInterface.getLogPanel().error("Failed to set value due to:" + t.getMessage());

              }

              public void onSuccess(Object arg0) {
                logStructureTreePanel.refreshData();

              }
            });

      }
    });

    setInterval.addClickListener(new ClickListener() {

      public void onClick(Widget arg0) {

        int di = -1;
        try {
          di = Integer.valueOf(_defaultNotificationInterval.getText()).intValue();
        }
        catch (Exception e) {
          UserInterface.getLogPanel().error("Failed to parse due:" + e.getMessage());
          return;
        }

        ServerConnection.logServiceAsync.setDefaultNotificationInterval(di, new AsyncCallback() {

          public void onFailure(Throwable t) {
            UserInterface.getLogPanel().error("Failed to set value due to:" + t.getMessage());

          }

          public void onSuccess(Object arg0) {
            // TODO Auto-generated method stub

          }
        });

      }
    });

    // Some fetches:
    ServerConnection.logServiceAsync.getDefaultNotificationInterval(new AsyncCallback() {

      public void onFailure(Throwable t) {
        UserInterface.getLogPanel().error("Failed to get value of default notification interval due to:" + t.getMessage());

      }

      public void onSuccess(Object o) {

        _defaultNotificationInterval.setText(o + "");
      }
    });
    ServerConnection.logServiceAsync.getDefaultHandlerLevel(new AsyncCallback() {

      public void onFailure(Throwable t) {
        UserInterface.getLogPanel().error("Failed to get value of default handler level due to:" + t.getMessage());

      }

      public void onSuccess(Object arg0) {
        setValue((String) arg0, _defaultHandlerLevel);

      }
    });

    ServerConnection.logServiceAsync.getDefaultLoggerLevel(new AsyncCallback() {

      public void onFailure(Throwable t) {
        UserInterface.getLogPanel().error("Failed to get value of default handler level due to:" + t.getMessage());

      }

      public void onSuccess(Object arg0) {
        setValue((String) arg0, _defaultLoggerLevel);

      }
    });
  }

  private void setValue(String name, ListBox box) {

    for (int i = 0; i < box.getItemCount(); i++) {
      if (box.getItemText(i).equals(name)) {
        box.setSelectedIndex(i);
        return;
      }
    }

  }

}


package javax.slee;

import java.io.Serializable;
import java.io.StreamCorruptedException;

/**
 * This class defines an enumerated type that encapsulates the values defining
 * whether an address has been screened by a user application.  The application can
 * choose one of these constants depending on whether it has screened the address
 * and the outcome received.
 *

 * A singleton instance of each enumerated value is guaranteed (via an implementation
 * of readResolve() - refer {@link java.io.Serializable java.io.Serializable}),
 * so that equality tests using == are always evaluated correctly.  (This
 * equality test is only guaranteed if this class is loaded in the application's boot class
 * path, rather than dynamically loaded at runtime.)
 * @see Address
 */
public final class AddressScreening implements Serializable{
    /**
     * An integer representation of {@link #UNDEFINED}.
     */
    public static final int ADDRESS_SCREENING_UNDEFINED = 0;

    /**
     * An integer representation of {@link #USER_NOT_VERIFIED}.
     */
    public static final int ADDRESS_SCREENING_USER_NOT_VERIFIED = 1;

    /**
     * An integer representation of {@link #USER_VERIFIED_PASSED}.
     */
    public static final int ADDRESS_SCREENING_USER_VERIFIED_PASSED = 2;

    /**
     * An integer representation of {@link #USER_VERIFIED_FAILED}.
     */
    public static final int ADDRESS_SCREENING_USER_VERIFIED_FAILED = 3;

    /**
     * An integer representation of {@link #NETWORK}.
     */
    public static final int ADDRESS_SCREENING_NETWORK = 4;

    /**
     * A string representation of {@link #UNDEFINED}.
     */
    public static final String UNDEFINED_STRING = "Undefined";

    /**
     * A string representation of {@link #USER_NOT_VERIFIED}.
     */
    public static final String USER_NOT_VERIFIED_STRING = "Not Verified";

    /**
     * A string representation of {@link #USER_VERIFIED_PASSED}.
     */
    public static final String USER_VERIFIED_PASSED_STRING = "User Verified Passed";

    /**
     * A string representation of {@link #USER_VERIFIED_FAILED}.
     */
    public static final String USER_VERIFIED_FAILED_STRING = "User Verified Failed";

    /**
     * A string representation of {@link #NETWORK}.
     */
    public static final String NETWORK_STRING = "Network";

    /**
     * The UNDEFINED value indicates that the address screening
     * is undefined.
     */
    public static final AddressScreening UNDEFINED = new AddressScreening(ADDRESS_SCREENING_UNDEFINED);

    /**
     * The USER_NOT_VERIFIED value indicates that the user-provided
     * address has not been verified.
     */
    public static final AddressScreening USER_NOT_VERIFIED = new AddressScreening(ADDRESS_SCREENING_USER_NOT_VERIFIED);

    /**
     * The USER_VERIFIED_PASSED value indicates that the user-provided
     * address has been verified and passed.
     */
    public static final AddressScreening USER_VERIFIED_PASSED = new AddressScreening(ADDRESS_SCREENING_USER_VERIFIED_PASSED);

    /**
     * The USER_VERIFIED_FAILED value indicates that the user-provider
     * address has been verified but failed.
     */
    public static final AddressScreening USER_VERIFIED_FAILED = new AddressScreening(ADDRESS_SCREENING_USER_VERIFIED_FAILED);

    /**
     * The NETWORK value indicates that the address is a
     * network or application provided address.
     */
    public static final AddressScreening NETWORK = new AddressScreening(ADDRESS_SCREENING_NETWORK);

    /**
     * Get an AddressScreening object from an integer value.
     * @param value the address screening value as an integer.
     * @return an AddressScreening object corresponding to value.
     * @throws IllegalArgumentException if value is not a valid
     *        address screening value.
     */
    public static AddressScreening fromInt(int value) throws IllegalArgumentException {
        switch (value) {
            case ADDRESS_SCREENING_UNDEFINED: return UNDEFINED;
            case ADDRESS_SCREENING_USER_NOT_VERIFIED: return USER_NOT_VERIFIED;
            case ADDRESS_SCREENING_USER_VERIFIED_PASSED: return USER_VERIFIED_PASSED;
            case ADDRESS_SCREENING_USER_VERIFIED_FAILED: return USER_VERIFIED_FAILED;
            case ADDRESS_SCREENING_NETWORK: return NETWORK;
            default: throw new IllegalArgumentException("Invalid value: " + value);
        }
    }

    /**
     * Get an AddressScreening object from a string value.
     * @param value the address screening as a string, for example as returned by the
              {@link #toString()} method (case insensitive).
     * @return an AddressScreening object corresponding to value.
     * @throws NullPointerException if value is null.
     * @throws IllegalArgumentException if value is not a valid
     *        address screening value.
     * @since SLEE 1.1
     */
    public AddressScreening fromString(String value) throws NullPointerException, IllegalArgumentException {
        if (value == null) throw new NullPointerException("value is null");
        if (value.equalsIgnoreCase(UNDEFINED_STRING)) return UNDEFINED;
        if (value.equalsIgnoreCase(USER_NOT_VERIFIED_STRING)) return USER_NOT_VERIFIED;
        if (value.equalsIgnoreCase(USER_VERIFIED_PASSED_STRING)) return USER_VERIFIED_PASSED;
        if (value.equalsIgnoreCase(USER_VERIFIED_FAILED_STRING)) return USER_VERIFIED_FAILED;
        if (value.equalsIgnoreCase(NETWORK_STRING)) return NETWORK;
        throw new IllegalArgumentException("Invalid value: " + value);
    }

    /**
     * Get an integer value representation for this AddressScreening object.
     * @return an integer value representation for this AddressScreening object.
     */
    public int toInt() {
        return value;
    }

    /**
     * Determine if this AddressScreening object represents the UNDEFINED address
     * screening value.
     *

     * This method is effectively equivalent to the conditional test:
     * (this == UNDEFINED), ie. the code:
     *

     *     if (screening.isUndefined()) ...
     *

     * is interchangeable with the code:
     *

     *    if (screening == AddressScreening.UNDEFINED) ...
     *

     * @return true if this object represents the UNDEFINED address screening
     *       value, false otherwise.
     */
    public boolean isUndefined() {
        return value == ADDRESS_SCREENING_UNDEFINED;
    }

    /**
     * Determine if this AddressScreening object represents the USER_NOT_VERIFIED address
     * screening value.
     *

     * This method is effectively equivalent to the conditional test:
     * (this == USER_NOT_VERIFIED), ie. the code:
     *

     *     if (screening.isUserNotVerified()) ...
     *

     * is interchangeable with the code:
     *

     *    if (screening == AddressScreening.USER_NOT_VERIFIED) ...
     *

     * @return true if this object represents the USER_NOT_VERIFIED address screening
     *       value, false otherwise.
     */
    public boolean isUserNotVerified() {
        return value == ADDRESS_SCREENING_USER_NOT_VERIFIED;
    }

    /**
     * Determine if this AddressScreening object represents the USER_VERIFIED_PASSED address
     * screening value.
     *

     * This method is effectively equivalent to the conditional test:
     * (this == USER_VERIFIED_PASSED), ie. the code:
     *

     *     if (screening.isUserVerifiedPassed()) ...
     *

     * is interchangeable with the code:
     *

     *    if (screening == AddressScreening.USER_VERIFIED_PASSED) ...
     *

     * @return true if this object represents the USER_VERIFIED_PASSED address screening
     *       value, false otherwise.
     */
    public boolean isUserVerifiedPassed() {
        return value == ADDRESS_SCREENING_USER_VERIFIED_PASSED;
    }

    /**
     * Determine if this AddressScreening object represents the USER_VERIFIED_FAILED address
     * screening value.
     *

     * This method is effectively equivalent to the conditional test:
     * (this == USER_VERIFIED_FAILED), ie. the code:
     *

     *     if (screening.isUserVerifiedFailed()) ...
     *

     * is interchangeable with the code:
     *

     *    if (screening == AddressScreening.USER_VERIFIED_FAILED) ...
     *

     * @return true if this object represents the USER_VERIFIED_FAILED address screening
     *       value, false otherwise.
     */
    public boolean isUserVerifiedFailed() {
        return value == ADDRESS_SCREENING_USER_VERIFIED_FAILED;
    }

    /**
     * Determine if this AddressScreening object represents the NETWORK address
     * screening value.
     *

     * This method is effectively equivalent to the conditional test:
     * (this == NETWORK), ie. the code:
     *

     *     if (screening.isNetword()) ...
     *

     * is interchangeable with the code:
     *

     *    if (screening == AddressScreening.NETWORK) ...
     *

     * @return true if this object represents the NETWORK address screening
     *       value, false otherwise.
     */
    public boolean isNetwork() {
        return value == ADDRESS_SCREENING_NETWORK;
    }

    /**
     * Compare this address screening for equality with another.
     * @param obj the object to compare this with.
     * @return true if obj is an instance of this class
     *        representing the same address screening value as this,
     *        false otherwise.
     */
    public boolean equals(Object obj) {
        if (obj == this) return true;

        return (obj instanceof AddressScreening)
            && ((AddressScreening)obj).value == value;
    }

    /**
     * Get a hash code value for this address screening.
     * @return a hash code value.
     */
    public int hashCode() {
        return value;
    }

    /**
     * Get the textual representation of the address screening object.
     * @return the textual representation of the address screening object.
     */
    public String toString() {
        switch (value) {
            case ADDRESS_SCREENING_UNDEFINED: return UNDEFINED_STRING;
            case ADDRESS_SCREENING_USER_NOT_VERIFIED: return USER_NOT_VERIFIED_STRING;
            case ADDRESS_SCREENING_USER_VERIFIED_PASSED: return USER_VERIFIED_PASSED_STRING;
            case ADDRESS_SCREENING_USER_VERIFIED_FAILED: return USER_VERIFIED_FAILED_STRING;
            case ADDRESS_SCREENING_NETWORK: return NETWORK_STRING;
            default: return "Address Screening in Unknown and Invalid State";
        }
    }

    /**
     * Private constructor to prevent unauthorized object creation.
     */
    private AddressScreening(int value) {
        this.value = value;
    }

    /**
     * Resolve deserialisation references so that the singleton property of each
     * enumerated object is preserved.
     */
    private Object readResolve() throws StreamCorruptedException {
        try {
            return fromInt(value);
        }
        catch (IllegalArgumentException iae) {
            throw new StreamCorruptedException("Invalid internal state found");
        }
    }

    private final int value;
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat, Inc. and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This 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 (at your option) any later version.
 *
 * This software 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 software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.mobicents.slee.container.component.deployment.jaxb.descriptors;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.slee.SLEEException;
import javax.slee.management.DeploymentException;

import org.mobicents.slee.container.component.deployment.jaxb.descriptors.ratype.MResourceAdaptorType;
import org.mobicents.slee.container.component.deployment.jaxb.descriptors.ratype.MResourceAdaptorTypeJar;
import org.mobicents.slee.container.component.ratype.ResourceAdaptorTypeDescriptorFactory;

/**
 *
 * Factory to build {@link ResourceAdaptorTypeDescriptorImpl} objects.
 *
 * @author  Alexandre Mendonca
 * @author  Bartosz Baranowski
 */
public class ResourceAdaptorTypeDescriptorFactoryImpl extends AbstractDescriptorFactory implements ResourceAdaptorTypeDescriptorFactory {

  /*
   * (non-Javadoc)
   * @see org.mobicents.slee.core.component.ratype.ResourceAdaptorTypeDescriptorFactory#parse(java.io.InputStream)
   */
  public List<ResourceAdaptorTypeDescriptorImpl> parse(InputStream inputStream) throws DeploymentException
  {
    Object jaxbPojo = buildJAXBPojo(inputStream);

    List<ResourceAdaptorTypeDescriptorImpl> result = new ArrayList<ResourceAdaptorTypeDescriptorImpl>();

    boolean isSlee11 = false;
    MResourceAdaptorTypeJar mResourceAdaptorTypeJar = null;
    if (jaxbPojo instanceof org.mobicents.slee.container.component.deployment.jaxb.slee.ratype.ResourceAdaptorTypeJar)
    {
      mResourceAdaptorTypeJar = new MResourceAdaptorTypeJar((org.mobicents.slee.container.component.deployment.jaxb.slee.ratype.ResourceAdaptorTypeJar)jaxbPojo);
    }
    else if (jaxbPojo instanceof org.mobicents.slee.container.component.deployment.jaxb.slee11.ratype.ResourceAdaptorTypeJar )
    {
      mResourceAdaptorTypeJar = new MResourceAdaptorTypeJar((org.mobicents.slee.container.component.deployment.jaxb.slee11.ratype.ResourceAdaptorTypeJar)jaxbPojo);
      isSlee11 = true;
    }
    else {
      throw new SLEEException("unexpected class of jaxb pojo built: "+(jaxbPojo != null ? jaxbPojo.getClass() : null));
    }

    for (MResourceAdaptorType mResourceAdaptorType : mResourceAdaptorTypeJar.getResourceAdaptorType())
    {
      result.add(new ResourceAdaptorTypeDescriptorImpl(mResourceAdaptorType, isSlee11));
    }

    return result;
  }
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat, Inc. and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This 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 (at your option) any later version.
 *
 * This software 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 software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.mobicents.slee.runtime.sbbentity;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;

import javax.slee.ActivityContextInterface;
import javax.slee.EventTypeID;
import javax.slee.SLEEException;
import javax.slee.SbbID;
import javax.slee.ServiceID;
import javax.slee.UnrecognizedEventException;

import org.apache.log4j.Logger;
import org.mobicents.slee.container.SleeContainer;
import org.mobicents.slee.container.SleeThreadLocals;
import org.mobicents.slee.container.activity.ActivityContext;
import org.mobicents.slee.container.activity.ActivityContextHandle;
import org.mobicents.slee.container.component.sbb.EventEntryDescriptor;
import org.mobicents.slee.container.component.sbb.GetChildRelationMethodDescriptor;
import org.mobicents.slee.container.component.sbb.SbbComponent;
import org.mobicents.slee.container.component.sbb.SbbComponent.EventHandlerMethod;
import org.mobicents.slee.container.component.service.ServiceComponent;
import org.mobicents.slee.container.event.EventContext;
import org.mobicents.slee.container.eventrouter.EventRoutingTransactionData;
import org.mobicents.slee.container.jndi.JndiManagement;
import org.mobicents.slee.container.sbb.SbbObject;
import org.mobicents.slee.container.sbb.SbbObjectPool;
import org.mobicents.slee.container.sbb.SbbObjectState;
import org.mobicents.slee.container.sbbentity.SbbEntity;
import org.mobicents.slee.container.sbbentity.SbbEntityID;
import org.mobicents.slee.container.transaction.TransactionContext;
import org.mobicents.slee.runtime.eventrouter.routingtask.EventRoutingTransactionDataImpl;
import org.mobicents.slee.runtime.sbb.SbbLocalObjectImpl;

/**
 *
 * This class is the Sbb Entity as defined in the Spec The SbbEntity class holds
 * the persistent state of the SbbEntity All the fields that are not transient
 * in this class they will be cached
 *
 * @author F. Moggia
 * @author M. Ranganathan
 * @author Tim
 * @author Ralf Siedow - bug fixes
 * @author eduardomartins
 *
 */
public class SbbEntityImpl implements SbbEntity {

	static private final Logger log = Logger.getLogger(SbbEntityImpl.class);

	private final SbbEntityID sbbeId; // This is the primary key of the SbbEntity.

	private SbbObject sbbObject;

	// cache some objects that may be expensive to retrieve from sbb entity id
	private SbbID _sbbID = null;
	private SbbObjectPool _pool = null;
	private SbbComponent _sbbComponent = null;

	// cache data
	protected SbbEntityCacheData cacheData;

	private final boolean created;

	private final SbbEntityFactoryImpl sbbEntityFactory;
	private final SleeContainer sleeContainer;

	private boolean doTraceLogs = log.isTraceEnabled();

	/**
	 * Call this constructor when there's no cached image and the Sbb entity is
	 * being created for the first time.
	 *
	 * @param container
	 * @param sbbeId
	 * @param sbbID
	 * @param convergenceName
	 * @param svcId
	 */
	SbbEntityImpl(SbbEntityID sbbEntityId, SbbEntityCacheData cacheData, boolean created, SbbEntityFactoryImpl sbbEntityFactory) {
		this.sbbEntityFactory = sbbEntityFactory;
		this.sleeContainer = sbbEntityFactory.getSleeContainer();
		this.sbbeId = sbbEntityId;
		this.cacheData = cacheData;
		this.created = created;
	}

	public ServiceID getServiceId() {
		return sbbeId.getServiceID();
	}

	public String getServiceConvergenceName() {
		return sbbeId.getServiceConvergenceName();
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.container.sbbentity.SbbEntity#getCMPField(java.lang.String)
	 */
	public Object getCMPField(String cmpFieldName) {
		if (log.isDebugEnabled()) {
			log.debug("Sbb entity "+getSbbEntityId()+" getting cmp field "+cmpFieldName);
		}
		sleeContainer.getTransactionManager().mandateTransaction();
		return cacheData.getCmpField(cmpFieldName);
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.container.sbbentity.SbbEntity#setCMPField(java.lang.String, java.lang.Object)
	 */
	public void setCMPField(String cmpFieldName, Object cmpFieldValue) {
		if (log.isDebugEnabled()) {
			log.debug("Sbb entity "+getSbbEntityId()+" setting cmp field "+cmpFieldName+" to value "+cmpFieldValue);
		}
		sleeContainer.getTransactionManager().mandateTransaction();
		cacheData.setCmpField(cmpFieldName, cmpFieldValue);
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.sbbentity.SbbEntity#afterACAttach(org.mobicents.slee.runtime.activity.ActivityContextHandle)
	 */
	public void afterACAttach(ActivityContextHandle ach) {

		// add to cache
		cacheData.attachActivityContext(ach);

		// update event mask
		Set<EventTypeID> maskedEvents = getSbbComponent().getDescriptor().getDefaultEventMask();
		if (maskedEvents != null && !maskedEvents.isEmpty()) {
			cacheData.updateEventMask(ach, new HashSet<EventTypeID>(maskedEvents));
		}

		if (log.isDebugEnabled()) {
			log.debug("Sbb entity "+getSbbEntityId()+" attached to AC with handle " + ach
					+ " , events added to current mask: " + maskedEvents);
		}
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.sbbentity.SbbEntity#afterACDetach(org.mobicents.slee.runtime.activity.ActivityContextHandle)
	 */
	public void afterACDetach(ActivityContextHandle ach) {

		// remove from cache
		cacheData.detachActivityContext(ach);

		if (log.isDebugEnabled()) {
			log.debug("Sbb entity "+getSbbEntityId()+" detached from AC with handle " + ach);
		}
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.sbbentity.SbbEntity#getMaskedEventTypes(org.mobicents.slee.runtime.activity.ActivityContextHandle)
	 */
	public Set<EventTypeID> getMaskedEventTypes(ActivityContextHandle ach) {
		return cacheData.getMaskedEventTypes(ach);
	}

	public void setEventMask(ActivityContextHandle ach, String[] eventMask)
			throws UnrecognizedEventException {

		HashSet<EventTypeID> maskedEvents = new HashSet<EventTypeID>();

		if (eventMask != null && eventMask.length != 0) {

			EventTypeID eventTypeID = null;
			EventEntryDescriptor sbbEventEntry = null;
			for (int i = 0; i < eventMask.length; i++) {

				eventTypeID = getSbbComponent().getDescriptor().getEventTypes().get(eventMask[i]);
				if (eventTypeID == null)
					throw new UnrecognizedEventException(
							"Event is not known by this SBB.");

				sbbEventEntry = getSbbComponent().getDescriptor()
						.getEventEntries().get(eventTypeID);
				if (sbbEventEntry.isReceived()) {
					maskedEvents.add(eventTypeID);
				} else {
					throw new UnrecognizedEventException("Event "
							+ eventMask[i]
							+ " has no receive direction for this SBB.");
				}
			}
		}

		cacheData.setEventMask(ach, maskedEvents);

		if (log.isDebugEnabled()) {
			log.debug("Sbb entity "+getSbbEntityId()+" set event mask for AC "+ach+". Masked events: " + maskedEvents);
		}

	}

	public Set<ActivityContextHandle> getActivityContexts() {
		return cacheData.getActivityContexts();
	}

	private static final String[] emptyStringArray = {};

	public String[] getEventMask(ActivityContextHandle ach) {

		Set<EventTypeID> maskedEvents = cacheData.getMaskedEventTypes(ach);

		if (doTraceLogs) {
			log.trace("SbbEntity "+getSbbEntityId()+" retrieved event mask for AC "+ach+". Masked events: " + maskedEvents);
		}

		if (maskedEvents == null || maskedEvents.isEmpty()) {
			return emptyStringArray;
		} else {
			String[] events = new String[maskedEvents.size()];
			Iterator<EventTypeID> evMaskIt = maskedEvents.iterator();
			for (int i = 0; evMaskIt.hasNext(); i++) {
				EventTypeID eventTypeId = evMaskIt.next();
				events[i] = getSbbComponent().getDescriptor().getEventEntries().get(
						eventTypeId).getEventName();
			}
			return events;
		}
	}

	public int getAttachmentCount() {
		int attachmentCount = getActivityContexts().size();
		// needs to add all children attachement counts too
		for (SbbEntityID sbbEntityId : cacheData.getAllChildSbbEntities()) {
			// recreated the sbb entity
			SbbEntity childSbbEntity = sbbEntityFactory.getSbbEntity(sbbEntityId, false);
			if (childSbbEntity != null) {
				attachmentCount += childSbbEntity.getAttachmentCount();
			}
		}
		return attachmentCount;
	}

	private Byte priority = null;

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.sbbentity.SbbEntity#getPriority()
	 */
	public byte getPriority() {
		if (priority == null) {
			priority = cacheData.getPriority();
		}
		if (priority == null) {
			// TODO check if alternative to fetch default priority and have non null only for custom performs good
			return 0;
		}
		return priority.byteValue();
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.sbbentity.SbbEntity#setPriority(byte)
	 */
	public void setPriority(byte value) {
		priority = Byte.valueOf(value);
		cacheData.setPriority(priority);
		if (log.isDebugEnabled()) {
			log.debug("Sbb entity "+getSbbEntityId()+" priority set to " + priority);
		}
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.sbbentity.SbbEntity#remove()
	 */
	public void remove() {

		if (doTraceLogs) {
			log.trace("remove()");
		}

		// removes the SBB entity from all Activity Contexts.
		for (Iterator<ActivityContextHandle> i = this.getActivityContexts().iterator(); i.hasNext();) {
			ActivityContextHandle ach = i.next();
			// get ac
			ActivityContext ac = sleeContainer.getActivityContextFactory().getActivityContext(ach);
			// remove the sbb entity from the attachment set.
			if (ac != null && !ac.isEnding()) {
				ac.detachSbbEntity(this.sbbeId);
			}
			// no need to remove ac from entity because the entity is being
			// removed
		}

		// It invokes the appropriate life cycle methods (see Section 6.3) of an
		// SBB object that caches the SBB entity state.
		boolean invokingServiceSet = SleeThreadLocals
				.getInvokingService() != null;
		if (!invokingServiceSet) {
			SleeThreadLocals.setInvokingService(getServiceId());
		}
		try {
			if (this.sbbObject == null) {
				this.assignSbbObject();
			}
			removeAndReleaseSbbObject();
		} catch (Exception e) {
			try {
				sleeContainer.getTransactionManager().setRollbackOnly();
				this.trashObject();
			} catch (Exception e2) {
				throw new RuntimeException("Transaction Failure.", e2);
			}
		} finally {
			if (!invokingServiceSet) {
				SleeThreadLocals.setInvokingService(null);
			}
		}

		// remove children
		for (SbbEntityID childSbbEntityId : cacheData.getAllChildSbbEntities()) {
			SbbEntity childSbbEntity = sbbEntityFactory.getSbbEntity(childSbbEntityId,false);
			if (childSbbEntity != null) {
				// recreate the sbb entity and remove it
				sbbEntityFactory.removeSbbEntity(childSbbEntity,false);
			}
		}

		cacheData.remove();

		if (log.isDebugEnabled()) {
			log.debug("Removed sbb entity " + getSbbEntityId());
		}
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.sbbentity.SbbEntity#trashObject()
	 */
	public void trashObject() {
		try {
			// FIXME shouldn't just return the object to the pool?
			getObjectPool().returnObject(sbbObject);
			this.sbbObject = null;
		} catch (Exception e) {
			throw new RuntimeException("Unexpected exception ", e);
		}
	}

	/* (non-Javadoc)
	 * @see org.mobicents.slee.runtime.sbbentity.SbbEntity#sbbRolledBack(java.lang.Object, javax.slee.ActivityContextInterface, boolean)
	 */
	public void sbbRolledBack(Object event,
			ActivityContextInterface activityContextInterface,
			boolean removeRollback) {
		if (sbbObject != null) {
			sbbObject.sbbRolledBack(event,activityContextInterface,removeRollback);
			passivateAndReleaseSbbObject();
		}
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.sbbentity.SbbEntity#getSbbEntityId()
	 */
	public SbbEntityID getSbbEntityId() {
		return this.sbbeId;
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.sbbentity.SbbEntity#getSbbId()
	 */
	public SbbID getSbbId() {
		if (_sbbID == null) {
			ServiceComponent serviceComponent = sleeContainer.getComponentRepository().getComponentByID(getServiceId());
			SbbComponent sbbComponent = null;
			if (sbbeId.isRootSbbEntity()) {
				_sbbID = serviceComponent.getRootSbbComponent().getSbbID();
			}
			else {
				// put chain of parent sbb entity ids in a stack
				final LinkedList<SbbEntityID> stack = new LinkedList<SbbEntityID>();
				SbbEntityID sbbEntityID = sbbeId.getParentSBBEntityID();
				while(!sbbEntityID.isRootSbbEntity()) {
					stack.push(sbbEntityID);
					sbbEntityID = sbbEntityID.getParentSBBEntityID();
				}
				// now find out the sbb component of the parent
				sbbComponent = serviceComponent.getRootSbbComponent();
				GetChildRelationMethodDescriptor getChildRelationMethodDescriptor = null;
				while(!stack.isEmpty()) {
					sbbEntityID = stack.pop();
					getChildRelationMethodDescriptor = sbbComponent.getDescriptor().getGetChildRelationMethodsMap().get(sbbEntityID.getParentChildRelation());
					sbbComponent = sleeContainer.getComponentRepository().getComponentByID(getChildRelationMethodDescriptor.getSbbID());
				}
				getChildRelationMethodDescriptor = sbbComponent.getDescriptor().getGetChildRelationMethodsMap().get(sbbeId.getParentChildRelation());
				_sbbID = getChildRelationMethodDescriptor.getSbbID();
			}
		}
		return _sbbID;
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.sbbentity.SbbEntity#invokeEventHandler(org.mobicents.slee.core.event.SleeEvent, org.mobicents.slee.runtime.activity.ActivityContext, org.mobicents.slee.core.event.EventContext)
	 */
	public void invokeEventHandler(EventContext sleeEvent, ActivityContext ac,
			EventContext eventContextImpl) throws Exception {

		// get event handler method
		final SbbComponent sbbComponent = getSbbComponent();
		final EventHandlerMethod eventHandlerMethod = sbbComponent
				.getEventHandlerMethods().get(sleeEvent.getEventTypeId());
		// build aci
		ActivityContextInterface aci = asSbbActivityContextInterface(ac.getActivityContextInterface());
		// now build the param array
		final Object[] parameters ;
		if (eventHandlerMethod.getHasEventContextParam()) {
			parameters = new Object[] { sleeEvent.getEvent(),
					aci, eventContextImpl };
		} else {
			parameters = new Object[] { sleeEvent.getEvent(),
					aci };
		}

		// store some info about the invocation in the tx context
		final EventRoutingTransactionData data = new EventRoutingTransactionDataImpl(
				sleeEvent, aci);
		final TransactionContext txContext = sleeContainer.getTransactionManager().getTransactionContext();
		txContext.setEventRoutingTransactionData(data);
		// track sbb entity invocations if reentrant
		Set<SbbEntityID> invokedSbbentities = null;
		if (!isReentrant()) {
			invokedSbbentities = txContext.getInvokedNonReentrantSbbEntities();
			invokedSbbentities.add(sbbeId);
		}
		final JndiManagement jndiManagement = sleeContainer.getJndiManagement();
		jndiManagement.pushJndiContext(sbbComponent);
		// invoke method
		try {

			//This is required. Since domain chain may indicate RA for instance, or SLEE deployer. If we dont do that test: tests/runtime/security/Test1112012Test.xml and second one, w
			//will fail because domain of SLEE tck ra is too restrictive (or we have bad desgin taht allows this to happen?)
			if(System.getSecurityManager()!=null) {
				AccessController.doPrivileged(new PrivilegedExceptionAction<Object>(){
				public Object run() throws IllegalAccessException, InvocationTargetException{
					eventHandlerMethod.getEventHandlerMethod().invoke(
							sbbObject.getSbbConcrete(), parameters);
					return null;
				}});
			}
			else {
				eventHandlerMethod.getEventHandlerMethod().invoke(
						sbbObject.getSbbConcrete(), parameters);
			}
		} catch(PrivilegedActionException pae) {
			Throwable cause = pae.getException();
			if(cause instanceof  IllegalAccessException)
			 {
				throw new RuntimeException(cause);
			} else if(cause instanceof InvocationTargetException ) {
				// Remember the actual exception is hidden inside the
				// InvocationTarget exception when you use reflection!
				Throwable realException = cause.getCause();
				if (realException instanceof RuntimeException) {
				    throw (RuntimeException) realException;
				} else if (realException instanceof Error) {
				    throw (Error) realException;
				} else if (realException instanceof Exception) {
				    throw (Exception) realException;
				}
			}else
			{
				pae.printStackTrace();
			}
		} catch(IllegalAccessException iae) {
			throw new RuntimeException(iae);
		} catch(InvocationTargetException ite) {
			Throwable realException = ite.getCause();
			if (realException instanceof RuntimeException) {
			    throw (RuntimeException) realException;
			} else if (realException instanceof Error) {
			    throw (Error) realException;
			} else if (realException instanceof Exception) {
			    throw (Exception) realException;
			}
		} catch(Exception e) {
			log.error(e.getMessage(),e);
		}
		finally {
			jndiManagement.popJndiContext();
			if(invokedSbbentities != null) {
				invokedSbbentities.remove(sbbeId);
			}
		}
		// remove data from tx context
		txContext.setEventRoutingTransactionData(null);

	}

	public ActivityContextInterface asSbbActivityContextInterface(
			ActivityContextInterface aci) {
		final SbbComponent sbbComponent = getSbbComponent();
		final Class<?> aciClass = sbbComponent.getActivityContextInterfaceConcreteClass();
		if (aciClass == null) {
			return aci;
		}
		else {
			try {
				return (ActivityContextInterface) aciClass
				.getConstructor(
						new Class[] { org.mobicents.slee.container.activity.ActivityContextInterface.class,
								SbbComponent.class }).newInstance(
										new Object[] { aci, sbbComponent });
			} catch (Exception e) {
				String s = "Could not create Custom ACI!";
				// log.error(s, e);
				throw new SLEEException(s, e);
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.sbbentity.SbbEntity#passivateAndReleaseSbbObject()
	 */
	public void passivateAndReleaseSbbObject() {
		this.sbbObject.sbbStore();
		this.sbbObject.sbbPassivate();
		this.sbbObject.setState(SbbObjectState.POOLED);
		this.sbbObject.setSbbEntity(null);
		try {
			getObjectPool().returnObject(this.sbbObject);
		} catch (Exception e) {
			log.error("failed to return sbb object "+sbbObject+" to pool",e);
		}
		this.sbbObject = null;
		if (childsWithSbbObjects != null) {
			for (Iterator<SbbEntity> i = childsWithSbbObjects.iterator(); i
			.hasNext();) {
				SbbEntity childSbbEntity = i.next();
				if (childSbbEntity.getSbbObject() != null) {
					Thread t = Thread.currentThread();
			    	ClassLoader cl = t.getContextClassLoader();
			        t.setContextClassLoader(childSbbEntity.getSbbComponent().getClassLoader());
					try {
						childSbbEntity.passivateAndReleaseSbbObject();
					}
					finally {
						t.setContextClassLoader(cl);
					}
				}
				i.remove();
			}
		}
	}

	/**
	 * Invoke sbbRemove() and then release the sbb object from the entity
	 *
	 * @throws Exception
	 */
	public void removeAndReleaseSbbObject() throws Exception {
		this.sbbObject.sbbStore();
		this.sbbObject.sbbRemove();
		this.sbbObject.setState(SbbObjectState.POOLED);
		this.sbbObject.setSbbEntity(null);
		getObjectPool().returnObject(this.sbbObject);
		this.sbbObject = null;
		if (childsWithSbbObjects != null) {
			for (Iterator<SbbEntity> i = childsWithSbbObjects.iterator(); i
			.hasNext();) {
				SbbEntity childSbbEntity = i.next();
				if (childSbbEntity.getSbbObject() != null) {
					Thread t = Thread.currentThread();
			    	ClassLoader cl = t.getContextClassLoader();
			        t.setContextClassLoader(childSbbEntity.getSbbComponent().getClassLoader());
					try {
						childSbbEntity.removeAndReleaseSbbObject();
					}
					finally {
						t.setContextClassLoader(cl);
					}
				}
				i.remove();
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.sbbentity.SbbEntity#getObjectPool()
	 */
	public SbbObjectPool getObjectPool() {
		if (_pool == null) {
			_pool = sleeContainer.getSbbManagement().getObjectPool(getServiceId(), getSbbId());
		}
		return this._pool;
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.sbbentity.SbbEntity#getSbbObject()
	 */
	public SbbObject getSbbObject() {
		return this.sbbObject;
	}

	public boolean isAttached(ActivityContextHandle ach) {
		return cacheData.isAttached(ach);
	}

	public SbbComponent getSbbComponent() {
		if (_sbbComponent == null) {
			_sbbComponent = sleeContainer.getComponentRepository().getComponentByID(getSbbId());
		}
		return _sbbComponent;
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.sbbentity.SbbEntity#getChildRelation(java.lang.String)
	 */
	public ChildRelationImpl getChildRelation(String accessorName) {
		return new ChildRelationImpl(this.getSbbComponent().getDescriptor()
				.getGetChildRelationMethodsMap().get(accessorName), this);
	}

	@Override
	public boolean equals(Object obj) {
		if (obj != null && obj.getClass() == this.getClass()) {
			return ((SbbEntityImpl) obj).sbbeId.equals(this.sbbeId);
		} else {
			return false;
		}
	}

	@Override
	public int hashCode() {
		return sbbeId.hashCode();
	}

	/**
	 * TODO improve with sbb local object storage
	 * @return
	 */
	public SbbLocalObjectImpl getSbbLocalObject() {

		if (doTraceLogs)
			log.trace("getSbbLocalObject()");

		// The concrete class generated in ConcreteLocalObjectGenerator
		final Class<?> sbbLocalClass = getSbbComponent().getSbbLocalInterfaceConcreteClass();
		if (sbbLocalClass != null) {
			Object[] objs = { this };
			Constructor<?> constructor = getSbbComponent().getSbbLocalObjectClassConstructor();
			if (constructor == null) {
				final Class<?>[] types = { SbbEntityImpl.class };
				try {
					constructor = sbbLocalClass.getConstructor(types);
				} catch (Throwable e) {
					throw new SLEEException("Unable to retrieve sbb local object generated class constructor",e);
				}
				getSbbComponent().setSbbLocalObjectClassConstructor(constructor);
			}
			try {
				return (SbbLocalObjectImpl) constructor.newInstance(objs);
			} catch (Throwable e) {
				throw new SLEEException(
						"Failed to create Sbb Local Interface.", e);
			}
		} else {
			return new SbbLocalObjectImpl(this);
		}
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.sbbentity.SbbEntity#isRemoved()
	 */
	public boolean isRemoved() {
		return cacheData.isRemoved() || !cacheData.exists();
	}

	/**
	 * Remove entity from cache.
	 */
	private void removeFromCache() {
		cacheData.remove();
	}
	private Set<SbbEntity> childsWithSbbObjects = null;

	protected void addChildWithSbbObject(SbbEntity childSbbEntity) {
		if (childsWithSbbObjects == null) {
			childsWithSbbObjects = new HashSet<SbbEntity>();
		}
		childsWithSbbObjects.add(childSbbEntity);
	}

	@Override
	public String toString() {
		return "SbbEntity:"+sbbeId;
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.sbbentity.SbbEntity#assignSbbObject()
	 */
	public void assignSbbObject() throws Exception {

		try {
			// get one object from the pool
			this.sbbObject = getObjectPool().borrowObject();
			// invoke the appropriate sbb life-cycle methods
			this.sbbObject.setSbbEntity(this);
			if (created) {
				this.sbbObject.sbbCreate();
				this.sbbObject.setState(SbbObjectState.READY);
				this.sbbObject.sbbPostCreate();
			}
			else {
				this.sbbObject.sbbActivate();
				this.sbbObject.setState(SbbObjectState.READY);
			}
			this.sbbObject.sbbLoad();
		} catch (Exception e) {
			log.error("Failed to assign and create sbb object", e);
			if (created) {
				removeFromCache();
			}
			throw e;
		}
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.runtime.sbbentity.SbbEntity#isCreated()
	 */
	public boolean isCreated() {
		return created;
	}

	/*
	 * (non-Javadoc)
	 * @see org.mobicents.slee.container.sbbentity.SbbEntity#isReentrant()
	 */
	public boolean isReentrant() {
		return getSbbComponent().isReentrant();
	}
}


/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat, Inc. and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This 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 (at your option) any later version.
 *
 * This software 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 software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

/**
 *
 */
package org.mobicents.slee.runtime.eventrouter.mapping;

import java.util.concurrent.atomic.AtomicInteger;

import org.mobicents.slee.container.activity.ActivityContextHandle;
import org.mobicents.slee.container.eventrouter.EventRouterExecutor;

/**
 * Round Robin {@link EventRouterExecutor} to {@link ActivityContextHandle} mapping.
 * @author martins
 *
 */
public class RoundRobinEventRouterExecutorMapper extends AbstractEventRouterExecutorMapper {

	/**
	 * index use to iterate the executor's array
	 */
	protected AtomicInteger index = null;

	/* (non-Javadoc)
	 * @see org.mobicents.slee.runtime.eventrouter.mapping.AbstractEventRouterExecutorMapper#setExecutors(org.mobicents.slee.runtime.eventrouter.EventRouterExecutor[])
	 */
	@Override
	public void setExecutors(EventRouterExecutor[] executors) {
		super.setExecutors(executors);
		//reset index
		index = new AtomicInteger(0);
	}

	/**
	 * Computes the index of the next executor to retrieve. Adaptation of the {@link AtomicInteger} incrementAndGet() code.
	 *
	 * @return
	 */
	private int getNextIndex() {
		for (;;) {
            int current = index.get();
            int next = (current == executors.length ? 1 : current + 1);
            if (index.compareAndSet(current, next))
                return next-1;
        }
	}

	/* (non-Javadoc)
	 * @see org.mobicents.slee.runtime.eventrouter.mapping.AbstractEventRouterExecutorMapper#getExecutor(org.mobicents.slee.runtime.activity.ActivityContextHandle)
	 */
	@Override
	public EventRouterExecutor getExecutor(
			ActivityContextHandle activityContextHandle) {
		return executors[getNextIndex()];
	}

}


/*
 * JBoss, Home of Professional Open Source
 * Copyright XXXX, Red Hat Middleware LLC, and individual contributors as indicated
 * by the @authors tag. All rights reserved.
 * See the copyright.txt in the distribution for a full listing
 * of individual contributors.
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * of the GNU General Public License, v. 2.0.
 * This program is distributed in the hope that it will be useful, but WITHOUT A
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License,
 * v. 2.0 along with this distribution; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 */
package org.mobicents.tools.twiddle.jslee;

import java.io.PrintWriter;

import javax.management.ObjectName;

/**
 * @author baranowb
 *
 */
public class ProfileUsageCommand extends AbstractUsageCommand {

	/**
	 *
	 */
	public ProfileUsageCommand() {
		super("usage.profile",
				"This command performs operations on JSLEE MBeans which are associated with usage parameter sets - be it specific MBean for parameter set, notification management MBean...");
	}

	/* (non-Javadoc)
	 * @see org.mobicents.tools.twiddle.jslee.AbstractUsageCommand#getProvisioningMBeanName()
	 */
	@Override
	public ObjectName getProvisioningMBeanName() {
		return super.PROFILE_PROVISIONING_MBEAN;
	}

	/* (non-Javadoc)
	 * @see org.mobicents.tools.twiddle.jslee.AbstractUsageCommand#getUsageMGMTMBeanOperation()
	 */
	@Override
	public String getUsageMGMTMBeanOperation() {

		return PROFILE_GET_METHOD;
	}

	/* (non-Javadoc)
	 * @see org.mobicents.tools.twiddle.jslee.AbstractUsageCommand#addExamples()
	 */
	@Override
	protected void addExamples(PrintWriter out) {
		out.println("");
		out.println("     1. List usage parameters type for profile table:");
		out.println("" + name + " CallControlTableName -l --parameters");
		out.println("");
		out.println("     2. List existing usage parameters sets:");
		out.println("" + name + " CallControlTableName -l --sets");
		out.println("");
		out.println("     3. Get value of parameter in certain set:");
		out.println("" + name + " CallControlTableName CertainSetWithValue -g --name=CookiesCount");
		out.println("");
		out.println("     4. Get value of parameter in certain set and reset value:");
		out.println("" + name + " CallControlTableName CertainSetWithValue -g --name=CookiesCount --rst");
		out.println("");
		out.println("     5. Reset all parameters in default parameter set of table:");
		out.println("" + name + " CallControlTableName --reset");
		out.println("");
		out.println("     6. Create parameter set:");
		out.println("" + name + " CallControlTableName NewSet --create");
		out.println("");
		out.println("     7. Enable notification generation for parameter:");
		out.println("" + name + " CallControlTableName -n --name=CookiesCount --value=true");

	}

	/* (non-Javadoc)
	 * @see org.mobicents.tools.twiddle.jslee.AbstractUsageCommand#addHeaderDescription()
	 */
	@Override
	protected void addHeaderDescription(PrintWriter out) {
		out.println("usage: " + name + " <ProfileTableName> [SetName] <-operation[[arg] | [--option[=arg]]*]>");
	}

}