package _VisualDVM.ComponentsServer; import Common.Database.Objects.DBObject; import Common.Database.RepositoryRefuseException; import Common.Utils.Utils_; import _VisualDVM.ComponentsServer.BugReport.BugReport; import _VisualDVM.ComponentsServer.BugReport.Json.BugReportAdditionJson; import _VisualDVM.ComponentsServer.Component.ComponentType; import _VisualDVM.ComponentsServer.Component.Json.ComponentPublicationInfoJson; import _VisualDVM.ComponentsServer.Component.Json.ComponentVersionsInfoJson; import _VisualDVM.ComponentsServer.UserAccount.AccountRole; import _VisualDVM.ComponentsServer.UserAccount.UserAccount; import _VisualDVM.Constants; import _VisualDVM.Global; import _VisualDVM.GlobalData.Machine.Machine; import _VisualDVM.GlobalData.Machine.MachineType; import _VisualDVM.GlobalData.RemoteFile.RemoteFile; import _VisualDVM.GlobalData.User.User; import _VisualDVM.Passes.All.ArchivesBackupPass; import _VisualDVM.Passes.All.UnzipFolderPass; import _VisualDVM.Passes.All.ZipFolderPass; import _VisualDVM.ProjectData.LanguageName; import _VisualDVM.Repository.EmailMessage; import _VisualDVM.Repository.Server.RepositoryServer; import _VisualDVM.Utils; import javafx.util.Pair; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.RandomStringUtils; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.Serializable; import java.lang.reflect.Field; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.Vector; public class ComponentsServer extends RepositoryServer { public CredentialsDatabase credentials_db = null; //-- public static ZipFolderPass zip = new ZipFolderPass(); public static UnzipFolderPass unzip = new UnzipFolderPass(); public static ArchivesBackupPass backupSession = new ArchivesBackupPass(); //- public static Vector> storages = new Vector<>( Arrays.asList(new Pair<>(new Machine("titan", "dvmh.keldysh.ru", 22, MachineType.Server), new User("dvmuser1", "mprit_2011")) )); //- protected Thread backUp = new Thread(() -> { while (true) { try { //------------------------------------- Calendar rightNow = Calendar.getInstance(); int year = rightNow.get(Calendar.YEAR); int month = rightNow.get(Calendar.MONTH); int day = rightNow.get(Calendar.DAY_OF_MONTH); int hour = rightNow.get(Calendar.HOUR_OF_DAY); int minute = rightNow.get(Calendar.MINUTE); if ((hour == Global.componentsServerProperties.BackupHour) && (minute == Global.componentsServerProperties.BackupMinute)) { //определить имя папки с багом. String backUpName = year + "_" + (month + 1) + "_" + (day); File todayBackUp = Paths.get(Global.DataBackUpsDirectory.getAbsolutePath(), backUpName).toFile(); File todayBackUpArchive = Paths.get(Global.DataBackUpsDirectory.getAbsolutePath(), backUpName + ".zip").toFile(); //- File bugsDBBackUp = Paths.get(todayBackUp.getAbsolutePath(), db.getFile().getName()).toFile(); File bugsArchives = Paths.get(todayBackUp.getAbsolutePath(), "Bugs.zip").toFile(); //- // Чистка старых бекапов на самом сервере. Utils.keepNewFiles(todayBackUp.getParentFile(), 2); if (!todayBackUpArchive.exists()) { FileUtils.forceMkdir(todayBackUp); Files.copy(db.getFile().toPath(), bugsDBBackUp.toPath()); //- zip.Do("Bugs", bugsArchives.getAbsolutePath()); zip.Do(todayBackUp.getAbsolutePath(), todayBackUpArchive.getAbsolutePath()); Utils_.forceDeleteWithCheck(todayBackUp); //- for (Pair cred : storages) { backupSession.Do(cred.getKey(), cred.getValue(), todayBackUpArchive); } //bonus backup //todo оформить как у планировщика, так как это нить, напрямую сервер трогать нельзя. if (rightNow.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) { EmailMessage message = new EmailMessage("db backup", "копия баз данных журнала ошибок"); message.addAttachement(db.getFile()); for (String address : Constants.admins_mails) { Email(message, address); } } } } //------------------------------------- Thread.sleep(60000); } catch (Exception ex) { Utils_.MainLog.PrintException(ex); } } }); public ComponentsServer() { super(BugReportsDatabase.class); } @Override public String getServerFileName() { return "VisualSapfor.jar"; } @Override public String getServerHomeName() { return "_sapfor_x64"; } @Override public int getPort() { return Constants.ComponentsServerPort; } @Override protected void beforePublishAction(DBObject object) throws Exception { if (object instanceof BugReport) { BugReport bugReport = (BugReport) object; if (bugReport.packed_archive != null) { File bugArchive = Utils_.getFile(Utils_.getHomePath(), "Bugs", bugReport.id); Utils_.bytesToFile(bugReport.packed_archive, bugArchive); } } } @Override protected void afterDeleteAction(DBObject object) throws Exception { if (object instanceof BugReport) { BugReport bugReport = (BugReport) object; if (!bugReport.project_version.isEmpty()) Utils_.forceDeleteWithCheck(bugReport.getArchiveFile()); } } @Override public void StartAction() throws Exception { if (Global.componentsServerProperties.EmailAdminsOnStart) { EmailMessage message = new EmailMessage("Сервер Sapfor запущен", new Date().toString()); for (String address : Constants.admins_mails) { Email(message, address); } } } @Override public void ActivateDB() { super.ActivateDB(); try { credentials_db = new CredentialsDatabase(); credentials_db.Activate(); } catch (Exception ex) { ex.printStackTrace(); } } @Override protected void startAdditionalThreads() { backUp.start(); } //- void DVMConvertProject() throws Exception { String[] args = request.arg.split("\n"); //- String projectName = args[0]; LanguageName projectLanguage = LanguageName.valueOf(args[1]); String options = args[2]; Vector filesNames = new Vector<>(Arrays.asList(args).subList(3, args.length)); //- File workspace = Utils.getTempFileName("convertation"); FileUtils.forceMkdir(workspace); File archive = new File(workspace, projectName + ".zip"); request.Unpack(archive); File project = new File(workspace, projectName); Vector badFiles = new Vector<>(); if (unzip.Do(archive.getAbsolutePath(), workspace.getAbsolutePath()) && project.exists()) { String output = ""; for (String fileName : filesNames) { File program = Paths.get(project.getAbsolutePath(), fileName).toFile(); //-- File convertedProgram = Paths.get(program.getParent(), Utils_.getFileNameWithoutExtension(program) + ".DVMH." + (projectLanguage.equals(LanguageName.fortran) ? "f" : "c")).toFile(); String command = Utils_.DQuotes(Constants.server_dvm_drv) + " " + projectLanguage.getDVMCompile() + "dv " + options + " " + Utils_.DQuotes(program.getName()); //-- File fileWorkspace = program.getParentFile(); Process process = Utils.startScript(workspace, fileWorkspace, Utils_.getDateName("convert_script"), command); process.waitFor(); String convertationOut = Utils.readAllOutput(process); convertationOut = convertationOut.replace(program.getName(), fileName); //для учета пути. if (!convertationOut.isEmpty()) output += convertationOut + "\n"; try { if (convertedProgram.exists()) { FileUtils.forceDelete(program); convertedProgram.renameTo(program); } else badFiles.add(program.getName()); } catch (Exception ex) { ex.printStackTrace(); } //-- } response.arg = String.join("\n", badFiles) + "|" + output; File resultArchive = new File(workspace, projectName + "_result.zip"); if (ComponentsServer.zip.Do(project.getAbsolutePath(), resultArchive.getAbsolutePath())) { response.object = Utils_.fileToBytes(resultArchive); } else throw new RepositoryRefuseException("Внутренняя ошибка. Не удалось запаковать версию"); //-- } else throw new RepositoryRefuseException("Внутренняя ошибка. Не удалось распаковать проект"); } void AppendBugReportField() throws Exception { BugReportAdditionJson transport = (BugReportAdditionJson) request.object; if (db.bugReports.containsKey(transport.id)) { BugReport actual = db.bugReports.get(transport.id); Field field = BugReport.class.getField(transport.fieldName); field.set(actual, field.get(actual) + "\n" + transport.textAddition); actual.change_date = new Date().getTime(); db.Update(actual); response.object = actual; } else throw new RepositoryRefuseException("Баг репорт с ключом " + transport.id + " не существует."); } void ReceiveAllArchives() throws Exception { ZipFolderPass zip = new ZipFolderPass(); File archives = new File(Utils_.getDateName("Bugs")); if (zip.Do("Bugs", archives.getAbsolutePath())) { response.object = Utils_.fileToBytes(archives); } else throw new RepositoryRefuseException("Не удалось запаковать архивы"); } void ReceiveBugReportsDatabase() throws Exception { response.object = Utils_.fileToBytes(db.getFile()); } void ReceiveBugReport() throws Exception { File bugArchive = Utils_.getFile(Utils_.getHomePath(), "Bugs", request.arg); response.object = Utils_.fileToBytes(bugArchive); } void UpdateBugReport() throws Exception { BugReport oldBugReport = (BugReport) request.object; if (db.bugReports.containsKey(oldBugReport.id)) { BugReport bugReport = db.bugReports.get(oldBugReport.id); bugReport.SynchronizeFields(oldBugReport); bugReport.change_date = new Date().getTime(); db.Update(bugReport); } else throw new RepositoryRefuseException("Баг репорт с ключом " + oldBugReport.id + " не существует."); } //-- void GetComponentsBackUps() throws Exception { File backupsDirectory = Paths.get(Utils_.getHomePath(), "Components", request.arg, "Backups").toFile(); //-- if (backupsDirectory.exists()) { File[] files = backupsDirectory.listFiles(File::isFile); if (files != null) { Vector res = new Vector<>(); for (File file : files) res.add(new RemoteFile(file.getAbsolutePath(), false)); //тут всегда линух. response.object = res; } else throw new RepositoryRefuseException("Не удалось получить список предыдущих версий"); } else { //баги еще не создавались. штатная ситуация. response.object = new Vector<>(); } } void CheckURLRegistered() throws Exception { String[] data = request.arg.split("\n"); String email = data[0]; String machineURL = data[1]; String login = data[2]; response.object = db.workspaces.findWorkspace(email, machineURL, login); } void GetComponentChangesLog() throws Exception { response.object = Utils_.fileToBytes(Paths.get(Utils_.getHomePath(), "Components", request.arg, "changes.txt").toFile()); } void PublishComponent() throws Exception { ComponentPublicationInfoJson info = (ComponentPublicationInfoJson) request.object; File componentHome = Utils_.getFile(Utils_.getHomePath(), "Components", info.componentType.toString()); File componentFile = new File(componentHome, info.fileName); File versionFile = new File(componentHome, "version.txt"); File backupsFolder = new File(componentHome, "Backups"); //0 архивация старой версии, если она есть. if (componentFile.exists()) { String versionText = ""; if (versionFile.exists()) versionText = Utils.ReadAllText(versionFile); //---->> Utils_.CheckDirectory(backupsFolder); Utils.keepNewFiles(backupsFolder, Global.componentsServerProperties.ComponentsBackUpsCount); //-->> File backupFile = new File(backupsFolder, info.componentType + "_" + versionText); if (backupFile.exists()) Utils_.forceDeleteWithCheck(backupFile); FileUtils.moveFile(componentFile, backupFile); } //1 распаковка компонента Utils_.bytesToFile((byte[]) info.packedFile, componentFile); //2 запись версии компонента FileUtils.writeStringToFile(versionFile, info.versionText); //3 запись в журнал компонента File changesLog = new File(componentHome, "changes.txt"); FileWriter writer = new FileWriter(changesLog.getAbsolutePath(), true); BufferedWriter bufferWriter = new BufferedWriter(writer); bufferWriter.write(info.changeRecord); bufferWriter.close(); //- if (info.needsUpdateMinimalVersion) { Print("Поднять минимальную версию компонента " + info.componentType); File minimal_versionFile = new File(componentHome, "minimal_version.txt"); FileUtils.writeStringToFile(minimal_versionFile, info.versionText); //- //3 запись в журнал компонента FileWriter writer_ = new FileWriter(changesLog, true); BufferedWriter bufferWriter_ = new BufferedWriter(writer_); bufferWriter_.write("Минимальная версия поднята до " + info.versionText + "\n"); bufferWriter_.close(); } } void GetComponentsVersionsInfo() throws Exception { Vector types = (Vector) request.object; Vector res = new Vector<>(); for (String sType : types) { ComponentType componentType = ComponentType.valueOf(sType); File actualVersionFile = Paths.get(Utils_.getHomePath(), "Components", sType, "version.txt").toFile(); File minimalVersionFile = Paths.get(Utils_.getHomePath(), "Components", sType, "minimal_version.txt").toFile(); ComponentVersionsInfoJson info = new ComponentVersionsInfoJson(componentType); info.actual_version = Utils_.removeCharacters(Utils.ReadAllText(actualVersionFile), "\n", "\r"); info.minimal_version = Utils_.removeCharacters(Utils.ReadAllText(minimalVersionFile), "\n", "\r"); res.add(info); } response.object = res; } void ReceiveComponent() throws Exception { String[] packed1 = request.arg.split("\n"); //тип/имя файла File componentFile1 = Paths.get(Utils_.getHomePath(), "Components", packed1[0], packed1[1]).toFile(); Print("Получить компонент " + packed1[0]); response.object = Utils_.fileToBytes(componentFile1); } void GetUserAccountByKey() throws Exception { UserAccount account = credentials_db.userAccounts.getByKey(request.arg); response.object = account == null ? null : account; } void GetUserAccountByEmail() throws Exception { UserAccount account_info = (UserAccount) request.object; UserAccount account = credentials_db.userAccounts.getByEmail(account_info.email); if (account == null) { account = new UserAccount(account_info); account.role = Constants.admins_mails.contains(account.email) ? AccountRole.Admin : AccountRole.User; credentials_db.Insert(account); account.generateKey(); } response.object = account; response.arg = FileUtils.readFileToString(account.getServerKeyFile()); } void ReceiveCredentialsDatabase() throws Exception { response.object = Utils_.fileToBytes(credentials_db.getFile()); } void PublishUserAccount() throws Exception { DBObject dbObject = (DBObject) request.object; response.object = (Serializable) credentials_db.InsertS(dbObject).getPK(); //-- credentials_db.userAccounts.get(response.object).generateKey(); } void EditUserAccount() throws Exception { UserAccount new_object = (UserAccount) request.object; credentials_db.UpdateWithCheck(new_object); } void DeleteUserAccount() throws Exception { } //-- @Override protected void UnsafeSession() throws Exception { switch (code) { case GetUserAccountByKey: GetUserAccountByKey(); break; case GetUserAccountByEmail: GetUserAccountByEmail(); break; case GetComponentsBackups: GetComponentsBackUps(); break; case UpdateComponent: //возможно со стороны админа ввод подтверждения по почте запрашивать. PublishComponent(); break; case ReceiveComponent: ReceiveComponent(); break; case CheckURLRegistered: CheckURLRegistered(); break; case GetComponentsVersionsInfo: GetComponentsVersionsInfo(); break; case GetComponentChangesLog: GetComponentChangesLog(); break; default: throw new RepositoryRefuseException("Неподдерживаемый код: " + code); } } @Override protected void Session() throws Exception { switch (code) { case PublishUserAccount: PublishUserAccount(); break; case EditUserAccount: EditUserAccount(); break; case ReceiveCredentialsDatabase: ReceiveCredentialsDatabase(); break; case ReceiveAllArchives: ReceiveAllArchives(); break; case UpdateBugReport: UpdateBugReport(); break; case AppendBugReportTextField: AppendBugReportField(); break; case ReceiveBugReportsDatabase: ReceiveBugReportsDatabase(); break; case ReceiveBugReport: ReceiveBugReport(); break; case DVMConvertProject: DVMConvertProject(); break; default: throw new RepositoryRefuseException("Неподдерживаемый код: " + code); } } }