Files
VisualSapfor/src/_VisualDVM/ComponentsServer/ComponentsServer.java

401 lines
19 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.Subscribes.Subscriber;
import _VisualDVM.ComponentsServer.UserAccount.UserAccount;
import _VisualDVM.Constants;
import _VisualDVM.Global;
import _VisualDVM.ComponentsServer.UserAccount.AccountRole;
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.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<BugReportsDatabase> {
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<Pair<Machine, User>> 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<Machine, User> 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);
}
}
//--
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<String> 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<String> 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<RemoteFile> 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<String> types = (Vector<String>) request.object;
Vector<ComponentVersionsInfoJson> 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;
account.security_key = RandomStringUtils.random(100, true, true);
credentials_db.Insert(account);
}
response.object = account;
}
//--
@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 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);
}
}
}