private void addServerIPAndHostEntries() {
    String hostName = serverConfigurationInformation.getHostName();
    String ipAddress = serverConfigurationInformation.getIpAddress();
    if (hostName != null && !"".equals(hostName)) {
      Entry entry = new Entry(SynapseConstants.SERVER_HOST);
      entry.setValue(hostName);
      synapseConfiguration.addEntry(SynapseConstants.SERVER_HOST, entry);
    }

    if (ipAddress != null && !"".equals(ipAddress)) {
      Entry entry = new Entry(SynapseConstants.SERVER_IP);
      entry.setValue(ipAddress);
      if (synapseConfiguration.getAxisConfiguration().getTransportsIn() != null) {
        Map<String, TransportInDescription> transportInConfigMap =
            synapseConfiguration.getAxisConfiguration().getTransportsIn();
        if (transportInConfigMap != null) {
          TransportInDescription transportInDescription = transportInConfigMap.get("http");
          if (transportInDescription != null) {
            Parameter bindAddressParam = transportInDescription.getParameter("bind-address");
            if (bindAddressParam != null) {
              entry.setValue(bindAddressParam.getValue());
            }
          }
        }
      }
      synapseConfiguration.addEntry(SynapseConstants.SERVER_IP, entry);
    }
  }
  /**
   * Create a Axis2 Based Server Environment
   *
   * @param serverConfigurationInformation ServerConfigurationInformation instance
   */
  private void createNewInstance(ServerConfigurationInformation serverConfigurationInformation) {

    try {
      configurationContext =
          ConfigurationContextFactory.createConfigurationContextFromFileSystem(
              serverConfigurationInformation.getAxis2RepoLocation(),
              serverConfigurationInformation.getAxis2Xml());

      configurationContext.setProperty(AddressingConstants.ADDR_VALIDATE_ACTION, Boolean.FALSE);

      startJmxAdapter();

      listenerManager = configurationContext.getListenerManager();
      if (listenerManager == null) {

        // create and initialize the listener manager but do not start
        listenerManager = new ListenerManager();
        listenerManager.init(configurationContext);
      }

      // do not use the listener manager shutdown hook, because it clashes with the
      // SynapseServer shutdown hook.
      listenerManager.setShutdownHookRequired(false);

    } catch (Throwable t) {
      handleFatal("Failed to create a new Axis2 instance...", t);
    }
  }
  /** Adds all Synapse proxy services to the Axis2 configuration. */
  private void deployProxyServices() {

    boolean failSafeProxyEnabled =
        SynapseConfigUtils.isFailSafeEnabled(SynapseConstants.FAIL_SAFE_MODE_PROXY_SERVICES);

    log.info("Deploying Proxy services...");
    String thisServerName = serverConfigurationInformation.getServerName();
    if (thisServerName == null || "".equals(thisServerName)) {
      thisServerName = serverConfigurationInformation.getHostName();
      if (thisServerName == null || "".equals(thisServerName)) {
        thisServerName = "localhost";
      }
    }

    for (ProxyService proxy : synapseConfiguration.getProxyServices()) {

      // start proxy service if either, pinned server name list is empty
      // or pinned server list has this server name
      List pinnedServers = proxy.getPinnedServers();
      if (pinnedServers != null && !pinnedServers.isEmpty()) {
        if (!pinnedServers.contains(thisServerName)) {
          log.info(
              "Server name not in pinned servers list."
                  + " Not deploying Proxy service : "
                  + proxy.getName());
          continue;
        }
      }

      try {
        AxisService proxyService =
            proxy.buildAxisService(
                synapseConfiguration, configurationContext.getAxisConfiguration());
        if (proxyService != null) {
          log.info("Deployed Proxy service : " + proxy.getName());
          if (!proxy.isStartOnLoad()) {
            proxy.stop(synapseConfiguration);
          }
        } else {
          log.warn("The proxy service " + proxy.getName() + " will NOT be available");
        }
      } catch (SynapseException e) {
        if (failSafeProxyEnabled) {
          log.warn(
              "The proxy service "
                  + proxy.getName()
                  + " cannot be deployed - "
                  + "Continue in Proxy Service fail-safe mode.");
        } else {
          handleException("The proxy service " + proxy.getName() + " : Deployment Error");
        }
      }
    }
  }
  /** {@inheritDoc} */
  public SynapseConfiguration createSynapseConfiguration() {

    String synapseXMLLocation = serverConfigurationInformation.getSynapseXMLLocation();
    Properties properties = SynapsePropertiesLoader.loadSynapseProperties();
    if (serverConfigurationInformation.getResolveRoot() != null) {
      properties.put(
          SynapseConstants.RESOLVE_ROOT, serverConfigurationInformation.getResolveRoot());
    }

    if (serverConfigurationInformation.getSynapseHome() != null) {
      properties.put(
          SynapseConstants.SYNAPSE_HOME, serverConfigurationInformation.getSynapseHome());
    }

    if (synapseXMLLocation != null) {
      synapseConfiguration =
          SynapseConfigurationBuilder.getConfiguration(synapseXMLLocation, properties);
    } else {
      log.warn(
          "System property or init-parameter '"
              + SynapseConstants.SYNAPSE_XML
              + "' is not specified. Using default configuration..");
      synapseConfiguration = SynapseConfigurationBuilder.getDefaultConfiguration();
    }

    Enumeration keys = properties.keys();
    while (keys.hasMoreElements()) {
      String key = (String) keys.nextElement();
      synapseConfiguration.setProperty(key, properties.getProperty(key));
    }

    // Set the Axis2 ConfigurationContext to the SynapseConfiguration
    synapseConfiguration.setAxisConfiguration(configurationContext.getAxisConfiguration());
    MessageContextCreatorForAxis2.setSynConfig(synapseConfiguration);

    // set the Synapse configuration into the Axis2 configuration
    Parameter synapseConfigurationParameter =
        new Parameter(SynapseConstants.SYNAPSE_CONFIG, synapseConfiguration);
    try {
      configurationContext.getAxisConfiguration().addParameter(synapseConfigurationParameter);
    } catch (AxisFault e) {
      handleFatal(
          "Could not set parameters '"
              + SynapseConstants.SYNAPSE_CONFIG
              + "' to the Axis2 configuration : "
              + e.getMessage(),
          e);
    }

    addServerIPAndHostEntries();

    return synapseConfiguration;
  }
  /**
   * Adds the synapse handlers to the inflow Dispatch phase and starts the listener manager if the
   * axis2 instance is created by the Synapse
   */
  public void start() {

    // add the Synapse handlers
    if (configurationContext != null) {
      List<Phase> inflowPhases = configurationContext.getAxisConfiguration().getInFlowPhases();
      for (Phase inPhase : inflowPhases) {
        // we are interested about the Dispatch phase in the inflow
        if (PhaseMetadata.PHASE_DISPATCH.equals(inPhase.getPhaseName())) {
          try {
            inPhase.addHandler(prepareSynapseDispatcher());
            inPhase.addHandler(prepareMustUnderstandHandler());
          } catch (PhaseException e) {
            handleFatal("Couldn't start Synapse, " + "Cannot add the required Synapse handlers", e);
          }
        }
      }
    } else {
      handleFatal("Couldn't start Synapse, ConfigurationContext not found");
    }

    // if the axis2 instance is created by us, then start the listener manager
    if (serverConfigurationInformation.isCreateNewInstance()) {
      if (listenerManager != null) {
        listenerManager.start();
      } else {
        handleFatal("Couldn't start Synapse, ListenerManager not found");
      }
      /* if JMX Adapter has been configured and started, output usage information rather
      at the end of the startup process to make it more obvious */
      if (jmxAdapter != null && jmxAdapter.isRunning()) {
        log.info(
            "Management using JMX available via: " + jmxAdapter.getJmxInformation().getJmxUrl());
      }
    }
  }
  /**
   * Starts the JMX Adaptor.
   *
   * @throws SynapseException if the JMX configuration is erroneous and/or the connector server
   *     cannot be started
   */
  private void startJmxAdapter() {
    Properties synapseProperties = SynapsePropertiesLoader.loadSynapseProperties();
    JmxInformation jmxInformation =
        JmxInformationFactory.createJmxInformation(
            synapseProperties, serverConfigurationInformation.getHostName());

    // Start JMX Adapter only if at least a JMX JNDI port is configured
    if (jmxInformation.getJndiPort() != -1) {
      jmxAdapter = new JmxAdapter(jmxInformation);
      jmxAdapter.start();
    }
  }
  /** {@inheritDoc} */
  public void destroy() {

    try {
      // only if we have created the server
      if (serverConfigurationInformation.isCreateNewInstance()) {

        // destroy listener manager
        if (listenerManager != null) {
          listenerManager.destroy();
        }

        stopJmxAdapter();
        RMIRegistryController.getInstance().shutDown();

        // we need to call this method to clean the temp files we created.
        if (configurationContext != null) {
          configurationContext.terminate();
        }
      }
      initialized = false;
    } catch (Exception e) {
      log.error("Error stopping the Axis2 Based Server Environment", e);
    }
  }
  /** Cleanup the axis2 environment and stop the synapse environment. */
  public void stop() {
    try {
      // stop tasks
      SynapseTaskManager synapseTaskManager = synapseEnvironment.getTaskManager();
      if (synapseTaskManager.isInitialized()) {
        synapseTaskManager.cleanup();
      }

      EnterpriseBeanstalkManager manager =
          (EnterpriseBeanstalkManager)
              serverContextInformation.getProperty(
                  EnterpriseBeanstalkConstants.BEANSTALK_MANAGER_PROP_NAME);
      if (manager != null) {
        manager.destroy();
      }

      // stop the listener manager
      if (listenerManager != null) {
        listenerManager.stop();
      }

      // detach the synapse handlers
      if (configurationContext != null) {
        List<Phase> inflowPhases = configurationContext.getAxisConfiguration().getInFlowPhases();
        for (Phase inPhase : inflowPhases) {
          // we are interested about the Dispatch phase in the inflow
          if (PhaseMetadata.PHASE_DISPATCH.equals(inPhase.getPhaseName())) {
            List<HandlerDescription> synapseHandlers = new ArrayList<HandlerDescription>();
            for (Handler handler : inPhase.getHandlers()) {
              if (SynapseDispatcher.NAME.equals(handler.getName())
                  || SynapseMustUnderstandHandler.NAME.equals(handler.getName())) {
                synapseHandlers.add(handler.getHandlerDesc());
              }
            }

            for (HandlerDescription handlerMD : synapseHandlers) {
              inPhase.removeHandler(handlerMD);
            }
          }
        }
      } else {
        handleException(
            "Couldn't detach the Synapse handlers, " + "ConfigurationContext not found.");
      }

      // continue stopping the axis2 environment if we created it
      if (serverConfigurationInformation.isCreateNewInstance()
          && configurationContext != null
          && configurationContext.getAxisConfiguration() != null) {
        Map<String, AxisService> serviceMap =
            configurationContext.getAxisConfiguration().getServices();
        for (AxisService svc : serviceMap.values()) {
          svc.setActive(false);
        }

        // stop all modules
        Map<String, AxisModule> moduleMap =
            configurationContext.getAxisConfiguration().getModules();
        for (AxisModule mod : moduleMap.values()) {
          if (mod.getModule() != null && !"synapse".equals(mod.getName())) {
            mod.getModule().shutdown(configurationContext);
          }
        }
      }
    } catch (AxisFault e) {
      log.error("Error stopping the Axis2 Environment");
    }
  }
  /**
   * {@inheritDoc}
   *
   * @param serverConfigurationInformation ServerConfigurationInformation Instance
   * @param serverContextInformation Server Context if the Axis2 Based Server Environment has been
   *     already set up.
   */
  public void init(
      ServerConfigurationInformation serverConfigurationInformation,
      ServerContextInformation serverContextInformation) {

    log.info("Initializing Synapse at : " + new Date());
    if (serverConfigurationInformation == null) {
      throw new IllegalArgumentException("ServerConfigurationInformation cannot be null");
    }

    if (serverContextInformation == null) {
      throw new IllegalArgumentException("ServerContextInformation cannot be null");
    }

    this.serverConfigurationInformation = serverConfigurationInformation;
    this.serverContextInformation = serverContextInformation;
    /* If no system property for the JMX agent is specified from outside, use a default one
    to show all MBeans (including the Axis2-MBeans) within the Synapse tree */
    if (System.getProperty(JMX_AGENT_NAME) == null) {
      System.setProperty(JMX_AGENT_NAME, "org.apache.synapse");
    }

    if (serverContextInformation.getServerContext() == null
        || serverConfigurationInformation.isCreateNewInstance()) {

      if (log.isDebugEnabled()) {
        log.debug("Initializing Synapse in a new axis2 server environment instance");
      }
      createNewInstance(serverConfigurationInformation);
    } else {
      Object context = serverContextInformation.getServerContext();
      if (context instanceof ConfigurationContext) {
        if (log.isDebugEnabled()) {
          log.debug(
              "Initializing Synapse in an already existing " + "axis2 server environment instance");
        }
        configurationContext = (ConfigurationContext) context;
        configurationContext.setProperty(AddressingConstants.ADDR_VALIDATE_ACTION, Boolean.FALSE);
      } else {
        handleFatal(
            "Synapse startup initialization failed : Provided server context is"
                + " invalid, expected an Axis2 ConfigurationContext instance");
      }
    }
    // set the configuration context
    serverContextInformation.setServerContext(configurationContext);

    // set the ServerContextInformation as a parameter
    Parameter serverContextParameter =
        new Parameter(SynapseConstants.SYNAPSE_SERVER_CTX_INFO, serverContextInformation);
    // set the ServerConfiguration as a parameter
    Parameter serverConfigParameter =
        new Parameter(SynapseConstants.SYNAPSE_SERVER_CONFIG_INFO, serverConfigurationInformation);
    try {
      configurationContext.getAxisConfiguration().addParameter(serverContextParameter);
      configurationContext.getAxisConfiguration().addParameter(serverConfigParameter);
    } catch (AxisFault ignored) {
      log.fatal("Error adding the parameter to the Axis Configuration");
    }

    // we retrieve these properties to initialize the task scheduler in the environment
    Object repo = serverContextInformation.getProperty(TaskConstants.TASK_DESCRIPTION_REPOSITORY);
    Object taskScheduler = serverContextInformation.getProperty(TaskConstants.TASK_SCHEDULER);

    if (repo != null && (repo instanceof TaskDescriptionRepository)) {
      this.taskDescriptionRepository = (TaskDescriptionRepository) repo;
    }

    if (taskScheduler != null && (taskScheduler instanceof TaskScheduler)) {
      this.taskScheduler = (TaskScheduler) taskScheduler;
    }

    addDefaultBuildersAndFormatters(configurationContext.getAxisConfiguration());
    initDataSourceHelper(serverContextInformation);
    initSharedSecretCallbackHandlerCache(serverContextInformation);
    initEnterpriseBeanstalkHolder(serverContextInformation);
    initialized = true;
  }