private void initPersistence(
      String configName,
      ConfigurationContext configurationContext,
      ServerContextInformation contextInfo)
      throws RegistryException, AxisFault {
    // Initialize the mediation persistence manager if required
    ServerConfiguration serverConf = ServerConfiguration.getInstance();
    String persistence = serverConf.getFirstProperty(ServiceBusConstants.PERSISTENCE);
    org.wso2.carbon.registry.core.Registry configRegistry =
        (org.wso2.carbon.registry.core.Registry)
            SuperTenantCarbonContext.getCurrentContext(configurationContext)
                .getRegistry(RegistryType.SYSTEM_CONFIGURATION);

    // Check whether persistence is disabled
    if (!ServiceBusConstants.DISABLED.equals(persistence)) {

      // Check registry persistence is disabled or not
      String regPersistence = serverConf.getFirstProperty(ServiceBusConstants.REGISTRY_PERSISTENCE);
      UserRegistry registry =
          ServiceBusConstants.DISABLED.equals(regPersistence)
              ? null
              : (UserRegistry) configRegistry;

      // Check the worker interval is set or not
      String interval = serverConf.getFirstProperty(ServiceBusConstants.WORKER_INTERVAL);
      long intervalInMillis = 5000L;
      if (interval != null && !"".equals(interval)) {
        try {
          intervalInMillis = Long.parseLong(interval);
        } catch (NumberFormatException e) {
          log.error(
              "Invalid value "
                  + interval
                  + " specified for the mediation "
                  + "persistence worker interval, Using defaults",
              e);
        }
      }

      MediationPersistenceManager pm =
          new MediationPersistenceManager(
              registry,
              contextInfo.getServerConfigurationInformation().getSynapseXMLLocation(),
              contextInfo.getSynapseConfiguration(),
              intervalInMillis,
              configName);

      configurationContext
          .getAxisConfiguration()
          .addParameter(new Parameter(ServiceBusConstants.PERSISTENCE_MANAGER, pm));
    } else {
      log.info("Persistence for mediation configuration is disabled");
    }
  }
 private synchronized void initEnterpriseBeanstalkHolder(
     ServerContextInformation serverContextInformation) {
   if (serverContextInformation.getProperty(
           EnterpriseBeanstalkConstants.BEANSTALK_MANAGER_PROP_NAME)
       == null) {
     EnterpriseBeanstalkManager beanstalkHolder = new EnterpriseBeanstalkManager();
     Properties synapseProperties = SynapsePropertiesLoader.reloadSynapseProperties();
     beanstalkHolder.init(synapseProperties);
     serverContextInformation.addProperty(
         EnterpriseBeanstalkConstants.BEANSTALK_MANAGER_PROP_NAME, beanstalkHolder);
   }
 }
 /**
  * Initiating SharedSecretCallbackHandlerCache reusing an existing SecretCallbackHandler instance
  * - a SecretCallbackHandler passed when start synapse.
  *
  * @param information ServerContextInformation instance
  */
 private void initSharedSecretCallbackHandlerCache(ServerContextInformation information) {
   SharedSecretCallbackHandlerCache cache = SharedSecretCallbackHandlerCache.getInstance();
   Object handler = information.getProperty(SecurityConstants.PROP_SECRET_CALLBACK_HANDLER);
   if (handler instanceof SecretCallbackHandler) {
     cache.setSecretCallbackHandler((SecretCallbackHandler) handler);
   }
 }
 /**
  * Initiating DataSourceRepositoryHolder with a new data source information repository or reusing
  * an existing repository.
  *
  * @param serverContextInformation ServerContextInformation instance
  */
 private void initDataSourceHelper(ServerContextInformation serverContextInformation) {
   DataSourceRepositoryHolder repositoryHolder = DataSourceRepositoryHolder.getInstance();
   Properties synapseProperties = SynapsePropertiesLoader.reloadSynapseProperties();
   Object repo =
       serverContextInformation.getProperty(
           DataSourceConstants.DATA_SOURCE_INFORMATION_REPOSITORY);
   if (repo instanceof DataSourceInformationRepository) {
     repositoryHolder.init((DataSourceInformationRepository) repo, synapseProperties);
   } else {
     repositoryHolder.init(null, synapseProperties);
   }
 }
  public void createdConfigurationContext(ConfigurationContext configurationContext) {
    ServerContextInformation contextInfo;
    String tenantDomain =
        SuperTenantCarbonContext.getCurrentContext(configurationContext).getTenantDomain();

    log.info("Intializing the ESB Configuration for the tenant domain : " + tenantDomain);

    try {
      // first check which configuration should be active
      org.wso2.carbon.registry.core.Registry registry =
          (org.wso2.carbon.registry.core.Registry)
              SuperTenantCarbonContext.getCurrentContext(configurationContext)
                  .getRegistry(RegistryType.SYSTEM_CONFIGURATION);

      AxisConfiguration axisConfig = configurationContext.getAxisConfiguration();

      // initialize the lock
      Lock lock = new ReentrantLock();
      axisConfig.addParameter(ServiceBusConstants.SYNAPSE_CONFIG_LOCK, lock);

      // creates the synapse configuration directory hierarchy if not exists
      // useful at the initial tenant creation
      File tenantAxis2Repo =
          new File(configurationContext.getAxisConfiguration().getRepository().getFile());
      File synapseConfigsDir = new File(tenantAxis2Repo, ServiceBusConstants.SYNAPSE_CONFIGS);
      if (!synapseConfigsDir.exists()) {
        if (!synapseConfigsDir.mkdir()) {
          log.fatal(
              "Couldn't create the synapse-config root on the file system "
                  + "for the tenant domain : "
                  + tenantDomain);
          return;
        }
      }

      String synapseConfigsDirLocation = synapseConfigsDir.getAbsolutePath();

      // set the required configuration parameters to initialize the ESB
      axisConfig.addParameter(
          SynapseConstants.Axis2Param.SYNAPSE_CONFIG_LOCATION, synapseConfigsDirLocation);

      // init the multiple configuration tracker
      ConfigurationManager manger =
          new ConfigurationManager((UserRegistry) registry, configurationContext);
      manger.init();

      File synapseConfigDir =
          new File(synapseConfigsDir, manger.getTracker().getCurrentConfigurationName());
      if (!synapseConfigDir.exists()) {
        createTenantSynapseConfigHierarchy(synapseConfigDir, tenantDomain);
      }

      axisConfig.addParameter(
          SynapseConstants.Axis2Param.SYNAPSE_HOME, tenantAxis2Repo.getAbsolutePath());
      axisConfig.addParameter(
          SynapseConstants.Axis2Param.SYNAPSE_SERVER_NAME, "synapse." + tenantDomain);
      axisConfig.addParameter(
          SynapseConstants.Axis2Param.SYNAPSE_RESOLVE_ROOT, tenantAxis2Repo.getAbsolutePath());

      // Initialize Synapse
      contextInfo =
          initESB(manger.getTracker().getCurrentConfigurationName(), configurationContext);

      if (contextInfo == null) {
        handleFatal("Failed to intilize the ESB for tenent:" + tenantDomain);
      }

      initPersistence(
          manger.getTracker().getCurrentConfigurationName(), configurationContext, contextInfo);

      configurationContext.setProperty(ConfigurationManager.CONFIGURATION_MANAGER, manger);

      int tenantId = SuperTenantCarbonContext.getCurrentContext(configurationContext).getTenantId();
      // populate the SynapseEnv service and SynapseConfig OSGI Services so that other
      // components get to know about the availability of the new synapse configuration
      Properties props = new Properties();
      SynapseConfigurationService synCfgSvc =
          new SynapseConfigurationServiceImpl(
              contextInfo.getSynapseConfiguration(), tenantId, configurationContext);

      ServiceRegistration confRegistration =
          ConfigurationHolder.getInstance()
              .getBundleContext()
              .registerService(SynapseConfigurationService.class.getName(), synCfgSvc, props);

      props = new Properties();
      SynapseEnvironmentService synEnvSvc =
          new SynapseEnvironmentServiceImpl(
              contextInfo.getSynapseEnvironment(), tenantId, configurationContext);
      ServiceRegistration envRegistration =
          ConfigurationHolder.getInstance()
              .getBundleContext()
              .registerService(SynapseEnvironmentService.class.getName(), synEnvSvc, props);

      props = new Properties();
      SynapseRegistrationsService synRegistrationsSvc =
          new SynapseRegistrationsServiceImpl(
              confRegistration, envRegistration, tenantId, configurationContext);
      ServiceRegistration synapseRegistration =
          ConfigurationHolder.getInstance()
              .getBundleContext()
              .registerService(
                  SynapseRegistrationsService.class.getName(), synRegistrationsSvc, props);

      ConfigurationTrackingService trackingService =
          ServiceBusInitializer.getConfigurationTrackingService();
      if (trackingService != null) {
        trackingService.setSynapseConfiguration(contextInfo.getSynapseConfiguration());
      }

      // set the event broker as a property for tenants
      EventBroker eventBroker = ServiceBusInitializer.getEventBroker();
      if (eventBroker != null) {
        configurationContext.setProperty("mediation.event.broker", eventBroker);
      }

      ConfigurationHolder.getInstance().addSynapseRegistration(tenantId, synapseRegistration);

    } catch (Exception e) {
      handleFatal("Couldn't initialize the ESB for tenant:" + tenantDomain, e);
    } catch (Throwable t) {
      log.fatal("Failed to initialize ESB for tenant:" + tenantDomain + "due to a fatal error", t);
    }
  }
  private ServerContextInformation initESB(
      String configurationName, ConfigurationContext configurationContext) throws AxisFault {
    ServerConfigurationInformation configurationInformation =
        ServerConfigurationInformationFactory.createServerConfigurationInformation(
            configurationContext.getAxisConfiguration());
    // ability to specify the SynapseServerName as a system property
    if (System.getProperty("SynapseServerName") != null) {
      configurationInformation.setServerName(System.getProperty("SynapseServerName"));
    }

    // for now we override the default configuration location with the value in registry
    String repoPath = configurationContext.getAxisConfiguration().getRepository().getPath();
    configurationInformation.setSynapseXMLLocation(
        repoPath
            + File.separator
            + ServiceBusConstants.SYNAPSE_CONFIGS
            + File.separator
            + configurationName);

    configurationInformation.setCreateNewInstance(false);
    configurationInformation.setServerControllerProvider(CarbonSynapseController.class.getName());
    if (isRunningSamplesMode()) {
      configurationInformation.setSynapseXMLLocation(
          "repository"
              + File.separator
              + "samples"
              + File.separator
              + "synapse_sample_"
              + System.getProperty(ServiceBusConstants.ESB_SAMPLE_SYSTEM_PROPERTY)
              + ".xml");
    }

    ServerManager serverManager = new ServerManager();
    ServerContextInformation contextInfo =
        new ServerContextInformation(configurationContext, configurationInformation);

    /*if (dataSourceInformationRepositoryService != null) {
        DataSourceInformationRepository repository =
                dataSourceInformationRepositoryService.getDataSourceInformationRepository();
        contextInfo.addProperty(DataSourceConstants.DATA_SOURCE_INFORMATION_REPOSITORY,
                repository);
    }*/

    TaskScheduler scheduler;
    if (configurationContext.getProperty(ServiceBusConstants.CARBON_TASK_SCHEDULER) == null) {
      scheduler = new TaskScheduler(TaskConstants.TASK_SCHEDULER);
      configurationContext.setProperty(ServiceBusConstants.CARBON_TASK_SCHEDULER, scheduler);
    } else {
      scheduler =
          (TaskScheduler)
              configurationContext.getProperty(ServiceBusConstants.CARBON_TASK_SCHEDULER);
    }
    contextInfo.addProperty(TaskConstants.TASK_SCHEDULER, scheduler);

    TaskDescriptionRepository repository;
    if (configurationContext.getProperty(ServiceBusConstants.CARBON_TASK_REPOSITORY) == null) {
      repository = new TaskDescriptionRepository();
      configurationContext.setProperty(ServiceBusConstants.CARBON_TASK_REPOSITORY, repository);
    } else {
      repository =
          (TaskDescriptionRepository)
              configurationContext.getProperty(ServiceBusConstants.CARBON_TASK_REPOSITORY);
    }
    contextInfo.addProperty(TaskConstants.TASK_DESCRIPTION_REPOSITORY, repository);

    /* if (secretCallbackHandlerService != null) {
        contextInfo.addProperty(SecurityConstants.PROP_SECRET_CALLBACK_HANDLER,
                secretCallbackHandlerService.getSecretCallbackHandler());
    }*/

    AxisConfiguration axisConf = configurationContext.getAxisConfiguration();
    axisConf.addParameter(
        new Parameter(ServiceBusConstants.SYNAPSE_CURRENT_CONFIGURATION, configurationName));

    serverManager.init(configurationInformation, contextInfo);
    serverManager.start();

    AxisServiceGroup serviceGroup = axisConf.getServiceGroup(SynapseConstants.SYNAPSE_SERVICE_NAME);
    serviceGroup.addParameter("hiddenService", "true");

    addDeployers(configurationContext);

    return contextInfo;
  }
  /**
   * Waits until it is safe to stop or the the specified end time has been reached. A delay of
   * <code>waitIntervalMillis</code> milliseconds is used between each subsequent check. If the
   * state "safeToStop" is reached before the specified <code>endTime</code>, the return value is
   * true.
   *
   * @param waitIntervalMillis the pause time (delay) in milliseconds between subsequent checks
   * @param endTime the time until which the checks need to finish successfully
   * @return true, if a safe state is reached before the specified <code>endTime</code>, otherwise
   *     false (forceful stop required)
   */
  public boolean waitUntilSafeToStop(long waitIntervalMillis, long endTime) {

    boolean safeToStop = false;
    boolean forcefulStop = false;
    Axis2TransportHelper transportHelper = new Axis2TransportHelper(configurationContext);

    // wait until it is safe to shutdown (listeners and tasks are idle, no callbacks)
    while (!safeToStop && !forcefulStop) {

      int pendingListenerThreads = transportHelper.getPendingListenerThreadCount();
      if (pendingListenerThreads > 0) {
        log.info(
            new StringBuilder("Waiting for: ")
                .append(pendingListenerThreads)
                .append(" listener threads to complete")
                .toString());
      }
      int pendingSenderThreads = transportHelper.getPendingSenderThreadCount();
      if (pendingSenderThreads > 0) {
        log.info(
            new StringBuilder("Waiting for: ")
                .append(pendingSenderThreads)
                .append(" listener threads to complete")
                .toString());
      }
      int activeConnections = transportHelper.getActiveConnectionsCount();
      if (activeConnections > 0) {
        log.info("Waiting for: " + activeConnections + " active connections to be closed..");
      }
      int pendingTransportThreads = pendingListenerThreads + pendingSenderThreads;

      int pendingCallbacks = serverContextInformation.getCallbackCount();
      if (pendingCallbacks > 0) {
        log.info("Waiting for: " + pendingCallbacks + " callbacks/replies..");
      }

      int runningTasks = 0;
      SynapseTaskManager synapseTaskManager = synapseEnvironment.getTaskManager();
      if (synapseTaskManager.isInitialized()) {
        runningTasks = synapseTaskManager.getTaskScheduler().getRunningTaskCount();
        if (runningTasks > 0) {
          log.info("Waiting for : " + runningTasks + " tasks to complete..");
        }
      }

      // it is safe to stop if all used listener threads, callbacks and tasks are zero
      safeToStop = ((pendingTransportThreads + pendingCallbacks + runningTasks) == 0);

      if (safeToStop) {
        log.info("All transport threads and tasks are idle and no pending callbacks..");
      } else {
        if (System.currentTimeMillis() < endTime) {
          log.info(
              new StringBuilder("Waiting for a maximum of another ")
                  .append((endTime - System.currentTimeMillis()) / 1000)
                  .append(" seconds until transport threads and tasks become idle, ")
                  .append("active connections to get closed,")
                  .append(" and callbacks to be completed..")
                  .toString());
          try {
            Thread.sleep(waitIntervalMillis);
          } catch (InterruptedException ignore) {
            // nothing to do here
          }
        } else {
          // maximum time to wait is over, do a forceful stop
          forcefulStop = true;
        }
      }
    }

    return !forcefulStop;
  }
  /** 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;
  }