Files
VisualSapfor/src/_VisualDVM/Repository/RepositoryServer.java

402 lines
17 KiB
Java
Raw Normal View History

2024-10-09 22:21:57 +03:00
package _VisualDVM.Repository;
2024-10-14 15:19:13 +03:00
import Common.Database.Database;
import Common.Database.Objects.DBObject;
2025-02-05 01:14:41 +03:00
import Common.Database.Objects.riDBObject;
import Common.Database.RepositoryRefuseException;
2024-10-14 15:19:13 +03:00
import Common.Utils.InterruptThread;
2024-10-11 00:00:30 +03:00
import Common.Utils.Utils_;
2024-10-09 22:01:19 +03:00
import _VisualDVM.Constants;
import _VisualDVM.Passes.Server.RepositoryPass;
2024-10-09 22:21:57 +03:00
import _VisualDVM.Repository.Server.DiagnosticSignalHandler;
import _VisualDVM.Repository.Server.SafeServerExchangeUnit;
2024-10-09 22:21:57 +03:00
import _VisualDVM.Repository.Server.ServerCode;
import _VisualDVM.Repository.Server.ServerExchangeUnit_2021;
2024-10-14 15:19:13 +03:00
import _VisualDVM.Utils;
2023-09-17 22:13:42 +03:00
import javafx.util.Pair;
import sun.misc.SignalHandler;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
2025-02-05 01:14:41 +03:00
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Properties;
import java.util.Vector;
2023-09-17 22:13:42 +03:00
public abstract class RepositoryServer<D extends Database> {
2024-10-14 15:19:13 +03:00
protected static FileWriter Log;
protected static boolean printOn = true;
public abstract String getServerFileName();
public abstract String getServerHomeName();
2024-10-14 15:19:13 +03:00
//-
public D db;
2023-09-17 22:13:42 +03:00
protected Socket clientSocket; //сокет для общения
protected ServerSocket server; // серверсокет
protected ObjectInputStream in; // поток чтения из сокета
protected ObjectOutputStream out; // поток записи в сокет
protected ServerExchangeUnit_2021 request;
protected ServerExchangeUnit_2021 response;
//-
protected ServerCode code;
protected long count = 0; //для отладки.
2024-10-14 15:19:13 +03:00
protected Thread interruptThread = new InterruptThread(10000,
() -> {
System.exit(0);
return null;
});
Class<D> d_class;
//-----------RECURSION ->
2023-09-17 22:13:42 +03:00
SignalHandler signalHandler = signal -> {
};
public RepositoryServer(Class<D> d_class_in) {
d_class = d_class_in;
}
2025-02-05 01:14:41 +03:00
protected static void ResetLog() {
if (printOn) {
try {
Log = new FileWriter("Log.txt", false);
Log.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
protected static void Print(String message) {
2023-09-17 22:13:42 +03:00
if (printOn) {
try {
Log = new FileWriter("Log.txt", true);
2024-10-11 00:00:30 +03:00
String dmessage = Utils_.Brackets("SESSION -> ") + new Date() +
" " + message;
Log.write(dmessage + "\n");
Log.close();
} catch (Exception ex) {
ex.printStackTrace();
}
2023-09-17 22:13:42 +03:00
}
}
2025-01-18 01:36:02 +03:00
//-DVMTestingChecker
2024-10-14 15:19:13 +03:00
public abstract int getPort();
protected void Session() throws Exception {};
protected void UnsafeSession() throws Exception {}
2024-10-14 15:19:13 +03:00
protected void startAdditionalThreads() {
}
public void ActivateDB() {
try {
db = d_class.newInstance();
db.Connect();
db.CreateAllTables();
db.prepareTablesStatements();
db.Synchronize();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void Email(EmailMessage message_in, String address_in) throws Exception {
Thread thread = new Thread(() -> {
try {
Properties props = new Properties();
props.put("mail.smtp.host", Constants.SMTPHost);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", String.valueOf(Constants.SMTPPort));
props.put("mail.smtp.socketFactory.port", String.valueOf(Constants.MailSocketPort));
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
2025-02-05 19:30:16 +03:00
props.put("mail.smtp.connectiontimeout", String.valueOf(15000));
props.put("mail.smtp.timeout", String.valueOf(15000));
props.put("mail.smtp.writetimeout", String.valueOf(15000));
//------------------------------
LinkedHashMap<String, File> innerFiles = new LinkedHashMap<>();
for (String aName : message_in.files.keySet()) {
File f = Utils.getTempFileName(aName);
2024-10-11 00:00:30 +03:00
Utils_.bytesToFile(message_in.files.get(aName), f);
innerFiles.put(aName, f);
2023-09-17 22:13:42 +03:00
}
//------------------------------
Session session = Session.getDefaultInstance(props,
new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
Constants.MailAddress,
Constants.MailPassword);
}
});
try {
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(Constants.MailAddress));
message.setRecipients(Message.RecipientType.CC, InternetAddress.parse(address_in));
message.setSubject(message_in.subject);
Multipart multipart = new MimeMultipart();
MimeBodyPart textBodyPart = new MimeBodyPart();
textBodyPart.setText(message_in.text);
multipart.addBodyPart(textBodyPart);
for (String aName : innerFiles.keySet()) {
MimeBodyPart attachmentBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(innerFiles.get(aName));
attachmentBodyPart.setDataHandler(new DataHandler(source));
attachmentBodyPart.setFileName(aName);
multipart.addBodyPart(attachmentBodyPart);
}
message.setContent(multipart);
Transport.send(message);
} catch (Exception ex) {
System.out.println("Исключение во время отправки сообщения абоненту " + Utils_.Brackets(address_in));
ex.printStackTrace();
Utils_.sleep(1000);
}
} catch (Exception ex) {
System.out.println("Исключение во время выполнения рассылки.");
ex.printStackTrace();
}
});
thread.start();
2023-09-17 22:13:42 +03:00
}
public boolean canDelete(DBObject object) throws Exception {
return true;
}
public void StartAction() throws Exception {
}
public void Start() throws Exception {
DiagnosticSignalHandler.install("TERM", signalHandler);
DiagnosticSignalHandler.install("INT", signalHandler);
DiagnosticSignalHandler.install("ABRT", signalHandler);
interruptThread.start();
2024-04-26 19:54:34 +03:00
startAdditionalThreads();
2023-09-17 22:13:42 +03:00
server = new ServerSocket(getPort());
StartAction();
while (true) {
try {
clientSocket = server.accept();
ResetLog();
2023-09-17 22:13:42 +03:00
Print((count++) + " клиент присоединился, IP=" + clientSocket.getInetAddress());
code = ServerCode.Undefined;
out = new ObjectOutputStream(clientSocket.getOutputStream());
in = new ObjectInputStream(clientSocket.getInputStream());
//->
DBObject dbObject = null;
Pair<Class, Object> p = null;
Print("Ожидание команды от клиента...");
Object transport = in.readObject();
Print("Команда прочитана.");
//-->
if (transport instanceof ServerExchangeUnit_2021) {
request = (ServerExchangeUnit_2021) transport;
response = new ServerExchangeUnit_2021(ServerCode.OK);
Print("клиент: <- " + (request.codeName));
//--
try {
code = request.getCode();
//--
if (transport instanceof SafeServerExchangeUnit){
SafeServerExchangeUnit safe_request= (SafeServerExchangeUnit) transport;
if (safe_request.version!=Constants.version){
//версия не совпала. не даем работать.
throw new RepositoryRefuseException("Версия клиента не совпадает с версией сервера!");
}
//БЕЗОПАСНАЯ СЕССИЯ
switch (code) {
case EditObject:
EditObject();
break;
case GetObjectCopyByPK:
GetObjectCopyByPK();
break;
case GetObjectsCopiesByPK:
GetObjectsCopiesByPK();
break;
case PublishObject:
PublishObject();
break;
case PublishObjects:
PublishObjects();
break;
case DeleteObjectByPK:
DeleteObjectByPK();
break;
case DeleteObjectsByPK:
DeleteObjectsByPK();
break;
case CloneObjectByPK:
CloneObject();
break;
default:
Session();
break;
}
}else {
//ОПАСНАЯ СЕССИЯ
switch (code){
case Ping:
Ping();
break;
case ReceiveFile:
ReceiveFile();
break;
case Email:
Email();
break;
default:
UnsafeSession();
break;
}
2023-09-17 22:13:42 +03:00
}
} catch (Exception ex) {
response = new ServerExchangeUnit_2021(ServerCode.FAIL, "Исключение сервера", ex);
} finally {
Print("сервер: -> " + response.codeName);
out.writeObject(response);
Print("Ответ отправлен.");
2023-09-17 22:13:42 +03:00
}
}
Print("Соединение с клиентом завершено.");
2023-09-17 22:13:42 +03:00
//->
} catch (Exception ex) {
Print("Исключение.Соединение с клиентом завершено.");
2023-09-17 22:13:42 +03:00
} finally {
//->
try {
if (clientSocket != null)
clientSocket.close();
} catch (Exception ex) {
ex.printStackTrace();
}
// потоки тоже хорошо бы закрыть
try {
if (in != null)
in.close();
} catch (Exception ex) {
ex.printStackTrace();
}
try {
if (out != null)
out.close();
} catch (Exception ex) {
ex.printStackTrace();
}
Print("Сервер ждет следующего клиента.");
}
}
}
//--
void Ping() {}
public boolean PingFromClient() {
RepositoryPass pingPass = new RepositoryPass(this) {
boolean success;
@Override
protected boolean needsAnimation() {
return true;
}
@Override
protected boolean canStart(Object... args) throws Exception {
success = false;
return true;
}
@Override
public String getDescription() {
return "Ping";
}
@Override
protected int getTimeout() {
return 0;
}
@Override
protected void body() throws Exception {
try {
super.body();
success = true;
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
protected void ServerAction() throws Exception {
2025-02-14 02:17:56 +03:00
unsafe_command(new ServerExchangeUnit_2021(ServerCode.Ping));
}
@Override
protected boolean validate() {
return success;
}
};
return pingPass.Do();
}
void ReceiveFile() throws Exception {
File file = new File(request.arg);
response.object = file.exists() ? Utils_.fileToBytes(file) : null;
}
void Email() throws Exception {
Email((EmailMessage) request.object, request.arg);
}
//----
void PublishObject() throws Exception {
DBObject dbObject = (DBObject) request.object;
beforePublishAction(dbObject);
response.object = (Serializable) db.InsertS(dbObject).getPK();
afterPublishAction(dbObject);
}
void PublishObjects() throws Exception {
Vector<DBObject> objects = (Vector<DBObject>) request.object;
for (DBObject dbObject : objects) {
beforePublishAction(dbObject);
response.object = (Serializable) db.InsertS(dbObject).getPK();
afterPublishAction(dbObject);
}
}
void CloneObject() throws Exception {
Pair<Class, Object> to_clone = (Pair<Class, Object>) request.object;
Object pk = to_clone.getValue();
if (db.getTable(to_clone.getKey()).containsKey(to_clone.getValue())) {
riDBObject src = (riDBObject) db.getTable(to_clone.getKey()).get(to_clone.getValue());
riDBObject dst = (riDBObject) to_clone.getKey().newInstance();
dst.SynchronizeFields(src);
//единственное отличие клона - текущий автор
dst.description += " копия";
String[] packed = request.arg.split("\n");
dst.sender_name = packed[0];
dst.sender_address = packed[1];
db.Insert(dst);
afterCloneAction(src, dst);
response.object = (Serializable) dst.getPK();
}
}
void GetObjectCopyByPK() throws Exception {
Pair<Class, Object> p = (Pair<Class, Object>) request.object;
DBObject dbObject = db.getObjectCopyByPK(p.getKey(), p.getValue());
response.object = dbObject;
}
void GetObjectsCopiesByPK() throws Exception {
Pair<Class, Object> p = (Pair<Class, Object>) request.object;
response.object = db.getObjectsCopies(p.getKey(), (Vector<Object>) p.getValue());
}
void EditObject() throws Exception {
DBObject new_object = (DBObject) request.object;
db.UpdateWithCheck(new_object);
afterEditAction(new_object);
}
void DeleteObjectByPK() throws Exception {
Pair<Class, Object> to_delete = (Pair<Class, Object>) request.object;
afterDeleteAction(db.DeleteByPK(to_delete.getKey(), to_delete.getValue()));
}
void DeleteObjectsByPK() throws Exception {
Pair<Class, Vector<Object>> to_delete = (Pair<Class, Vector<Object>>) request.object;
for (Object object : to_delete.getValue()) {
afterDeleteAction(db.DeleteByPK(to_delete.getKey(), object));
}
}
protected void afterCloneAction(riDBObject src, riDBObject dst) throws Exception {
}
protected void beforePublishAction(DBObject object) throws Exception {
}
protected void afterPublishAction(DBObject object) throws Exception {
}
protected void afterEditAction(DBObject object) throws Exception {
}
protected void afterDeleteAction(DBObject object) throws Exception {
}
2023-09-17 22:13:42 +03:00
}