+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @file task_prepare_reinstall.cpp
+ * @author Jihoon Chung(jihoon.chung@samsung.com)
+ * @version 1.0
+ * @brief Implementation file for installer task prepare reinstalling
+ */
+
+#include "task_prepare_reinstall.h"
+
+#include <stdio.h>
+#include <fstream>
+
+#include <dpl/task.h>
+#include <dpl/string.h>
+#include <dpl/log/log.h>
+#include <dpl/foreach.h>
+
+#include <widget_install/widget_install_context.h>
+#include <widget_install/widget_install_errors.h>
+#include <widget_install/job_widget_install.h>
+
+namespace Jobs {
+namespace WidgetInstall {
+namespace {
+const char* const KEY_DELETE = "#delete";
+const char* const KEY_ADD = "#add";
+const char* const KEY_MODIFY = "#modify";
+std::list<std::string> keyList = {KEY_DELETE, KEY_ADD, KEY_MODIFY};
+
+void verifyFile(const std::string &filePath)
+{
+ if (access(filePath.c_str(), F_OK) != 0) {
+ ThrowMsg(Exceptions::AceCheckFailed, "File is missed " << filePath);
+ }
+}
+}
+
+TaskPrepareReinstall::TaskPrepareReinstall(InstallerContext& context) :
+ DPL::TaskDecl<TaskPrepareReinstall>(this),
+ m_context(context)
+{
+ AddStep(&TaskPrepareReinstall::StepPrepare);
+ AddStep(&TaskPrepareReinstall::StepParseRDSDelta);
+ AddStep(&TaskPrepareReinstall::StepVerifyRDSDelta);
+ AddStep(&TaskPrepareReinstall::StepAddFile);
+ AddStep(&TaskPrepareReinstall::StepDeleteFile);
+ AddStep(&TaskPrepareReinstall::StepModifyFile);
+}
+
+void TaskPrepareReinstall::StepPrepare()
+{
+ LogInfo("Prepare");
+ m_sourcePath = m_context.locations->getTemporaryPackageDir();
+ m_sourcePath += "/";
+
+ m_installedPath = m_context.locations->getPackageInstallationDir();
+ m_installedPath += "/";
+}
+
+void TaskPrepareReinstall::StepParseRDSDelta()
+{
+ LogInfo("parse RDS delta");
+ std::string rdsDeltaPath = m_sourcePath;
+ rdsDeltaPath += ".rds_delta";
+ std::ifstream delta(rdsDeltaPath);
+
+ if (!delta.is_open()) {
+ // TODO throw exception
+ ThrowMsg(Exceptions::RDSDeltaFailure, "rds_delta file is missed");
+ return;
+ }
+
+ std::string line;
+ std::string key;
+ while (std::getline(delta, line) &&!delta.eof()) {
+ FOREACH(keyIt, keyList) {
+ if (line == *keyIt) {
+ LogInfo("find key = [" << line << "]");
+ key = line;
+ break;
+ }
+ }
+ if (key == line || line.empty() || line == "\n") {
+ continue;
+ }
+ if (key == KEY_DELETE) {
+ m_deleteFileList.push_back(line);
+ LogInfo("line = [" << line << "]");
+ } else if (key == KEY_ADD) {
+ m_addFileList.push_back(line);
+ LogInfo("line = [" << line << "]");
+ } else if (key == KEY_MODIFY) {
+ m_modifyFileList.push_back(line);
+ LogInfo("line = [" << line << "]");
+ }
+ }
+}
+
+void TaskPrepareReinstall::StepVerifyRDSDelta()
+{
+ LogInfo("verify RDS delta");
+ // Verify ADD file
+ FOREACH(file, m_addFileList) {
+ std::string addFilePath = m_sourcePath;
+ addFilePath += *file;
+ verifyFile(addFilePath);
+ }
+ // Verify DELETE file
+ FOREACH(file, m_deleteFileList) {
+ std::string deleteFilePath = m_installedPath;
+ deleteFilePath += *file;
+ verifyFile(deleteFilePath);
+ }
+ // Verify MODIFY file
+ FOREACH(file, m_modifyFileList) {
+ std::string newFilePath = m_sourcePath;
+ newFilePath += *file;
+ verifyFile(newFilePath);
+
+ std::string existingFilePath = m_installedPath;
+ existingFilePath += *file;
+ verifyFile(existingFilePath);
+ }
+ LogInfo("Finished veify RDS Delta");
+
+ m_context.job->UpdateProgress(
+ InstallerContext::INSTALL_RDS_DELTA_CHECK,
+ "RDS delta verify finished");
+}
+
+void TaskPrepareReinstall::StepAddFile()
+{
+ LogInfo("Add file");
+ FOREACH(file, m_addFileList) {
+ std::string newfile = m_sourcePath;
+ newfile += *file;
+ std::string destPath = m_installedPath;
+ destPath += *file;
+ if (rename(newfile.c_str(), destPath.c_str()) != 0) {
+ ThrowMsg(Exceptions::RDSDeltaFailure,
+ "Fail to ADD file " << newfile);
+ }
+ LogInfo("Copy " << newfile << " to " << destPath);
+ }
+}
+
+void TaskPrepareReinstall::StepDeleteFile()
+{
+ LogInfo("Delete file");
+ FOREACH(file, m_deleteFileList) {
+ std::string deleteFilePath = m_installedPath;
+ deleteFilePath += *file;
+ if (remove(deleteFilePath.c_str()) != 0) {
+ ThrowMsg(Exceptions::RDSDeltaFailure,
+ "Fail to DELETE file " << deleteFilePath);
+ }
+ LogInfo("Delete " << deleteFilePath);
+ }
+}
+
+void TaskPrepareReinstall::StepModifyFile()
+{
+ LogInfo("Modify file");
+ FOREACH(file, m_modifyFileList) {
+ std::string destPath = m_installedPath;
+ destPath += *file;
+ if (remove(destPath.c_str()) != 0) {
+ ThrowMsg(Exceptions::RDSDeltaFailure,
+ "Fail to delete existing file " << destPath);
+ }
+
+ std::string newfile = m_sourcePath;
+ newfile += *file;
+ if (rename(newfile.c_str(), destPath.c_str()) != 0) {
+ ThrowMsg(Exceptions::RDSDeltaFailure,
+ "Fail to move new file" << destPath);
+ }
+ LogInfo("Replace " << newfile << " to " << destPath);
+ }
+ m_context.job->UpdateProgress(
+ InstallerContext::INSTALL_RDS_PREPARE,
+ "RDS prepare finished");
+}
+
+} //namespace WidgetInstall
+} //namespace Jobs