public function AsyncAction(WebPage $oPage, $sCode, $aParameters)
    {
        $oParameters = new PHPParameters();
        $sStep = $aParameters['installer_step'];
        $sJSONParameters = $aParameters['installer_config'];
        $oParameters->LoadFromHash(json_decode($sJSONParameters, true));
        $oInstaller = new ApplicationInstaller($oParameters);
        $aRes = $oInstaller->ExecuteStep($sStep);
        if ($aRes['status'] != ApplicationInstaller::ERROR && $aRes['next-step'] != '') {
            // Tell the web page to move the progress bar and to launch the next step
            $sMessage = addslashes(htmlentities($aRes['next-step-label'], ENT_QUOTES, 'UTF-8'));
            $oPage->add_ready_script(<<<EOF
\t\$("#wiz_form").data("installation_status", "running");
\tWizardUpdateButtons();
\t\$('#setup_msg').html('{$sMessage}');
\t\$('#progress').progression( {Current:{$aRes['percentage-completed']}, Maximum: 100, aBackgroundImg: GetAbsoluteUrlAppRoot()+'setup/orange-progress.gif', aTextColor: '#000000'} );
\t
\t//\$("#percentage").html('{$aRes['percentage-completed']} % completed<br/>{$aRes['next-step-label']}');
\tExecuteStep('{$aRes['next-step']}');
EOF
);
        } else {
            if ($aRes['status'] != ApplicationInstaller::ERROR) {
                // Installation complete, move to the next step of the wizard
                $oPage->add_ready_script(<<<EOF
\t\$("#wiz_form").data("installation_status", "completed");
\t\$('#progress').progression( {Current:100, Maximum: 100, aBackgroundImg: GetAbsoluteUrlAppRoot()+'setup/orange-progress.gif', aTextColor: '#000000'} );
\tWizardUpdateButtons();
\t\$("#btn_next").unbind("click.install");
\t\$("#btn_next").click();
EOF
);
            } else {
                $sMessage = addslashes(htmlentities($aRes['message'], ENT_QUOTES, 'UTF-8'));
                $oPage->add_ready_script(<<<EOF
\t\$("#wiz_form").data("installation_status", "error");
\tWizardUpdateButtons();
\t\$('#setup_msg').html('{$sMessage}');
EOF
);
            }
        }
    }
 protected static function DoLoadFiles($aSelectedModules, $sModulesDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sTargetEnvironment = '', $bOldAddon = false, $bSampleData = false)
 {
     $aParamValues = array('db_server' => $sDBServer, 'db_user' => $sDBUser, 'db_pwd' => $sDBPwd, 'db_name' => $sDBName, 'new_db_name' => $sDBName, 'db_prefix' => $sDBPrefix);
     $oConfig = new Config();
     $oConfig->UpdateFromParams($aParamValues, $sModulesDir);
     if ($bOldAddon) {
         // Old version of the add-on for backward compatibility with pre-2.0 data models
         $oConfig->SetAddons(array('user rights' => 'addons/userrights/userrightsprofile.db.class.inc.php'));
     }
     //Load the MetaModel if needed (asynchronous mode)
     if (!self::$bMetaModelStarted) {
         $oProductionEnv = new RunTimeEnvironment($sTargetEnvironment);
         $oProductionEnv->InitDataModel($oConfig, false);
         // load data model and connect to the database
         self::$bMetaModelStarted = true;
         // No need to reload the final MetaModel in case the installer runs synchronously
     }
     $oDataLoader = new XMLDataLoader();
     CMDBObject::SetTrackInfo("Initialization");
     $oMyChange = CMDBObject::GetCurrentChange();
     SetupPage::log_info("starting data load session");
     $oDataLoader->StartSession($oMyChange);
     $aFiles = array();
     $aPreviouslyLoadedFiles = array();
     $oProductionEnv = new RunTimeEnvironment();
     $aAvailableModules = $oProductionEnv->AnalyzeInstallation($oConfig, APPROOT . $sModulesDir);
     foreach ($aAvailableModules as $sModuleId => $aModule) {
         if ($sModuleId != ROOT_MODULE) {
             // Load data only for selected AND newly installed modules
             if (in_array($sModuleId, $aSelectedModules)) {
                 if ($aModule['version_db'] != '') {
                     // Simulate the load of the previously loaded XML files to get the mapping of the keys
                     if ($bSampleData) {
                         $aPreviouslyLoadedFiles = array_merge($aPreviouslyLoadedFiles, $aAvailableModules[$sModuleId]['data.struct'], $aAvailableModules[$sModuleId]['data.sample']);
                     } else {
                         // Load only structural data
                         $aPreviouslyLoadedFiles = array_merge($aPreviouslyLoadedFiles, $aAvailableModules[$sModuleId]['data.struct']);
                     }
                 } else {
                     if ($bSampleData) {
                         $aFiles = array_merge($aFiles, $aAvailableModules[$sModuleId]['data.struct'], $aAvailableModules[$sModuleId]['data.sample']);
                     } else {
                         // Load only structural data
                         $aFiles = array_merge($aFiles, $aAvailableModules[$sModuleId]['data.struct']);
                     }
                 }
             }
         }
     }
     // Simulate the load of the previously loaded files, in order to initialize
     // the mapping between the identifiers in the XML and the actual identifiers
     // in the current database
     foreach ($aPreviouslyLoadedFiles as $sFileRelativePath) {
         $sFileName = APPROOT . $sFileRelativePath;
         SetupPage::log_info("Loading file: {$sFileName} (just to get the keys mapping)");
         if (empty($sFileName) || !file_exists($sFileName)) {
             throw new Exception("File {$sFileName} does not exist");
         }
         $oDataLoader->LoadFile($sFileName, true);
         $sResult = sprintf("loading of %s done.", basename($sFileName));
         SetupPage::log_info($sResult);
     }
     foreach ($aFiles as $sFileRelativePath) {
         $sFileName = APPROOT . $sFileRelativePath;
         SetupPage::log_info("Loading file: {$sFileName}");
         if (empty($sFileName) || !file_exists($sFileName)) {
             throw new Exception("File {$sFileName} does not exist");
         }
         $oDataLoader->LoadFile($sFileName);
         $sResult = sprintf("loading of %s done.", basename($sFileName));
         SetupPage::log_info($sResult);
     }
     $oDataLoader->EndSession();
     SetupPage::log_info("ending data load session");
 }