Files
VisualSapfor/src/_VisualDVM/Repository/RepositoryServer.java
02090095 e259a3c2a9 v++
Любое взаимодействие с серверами сведено до единстенной команды.
2025-02-05 01:40:28 +03:00

409 lines
20 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.Repository;
import Common.Database.Database;
import Common.Database.Objects.DBObject;
import Common.Database.Objects.riDBObject;
import Common.Utils.InterruptThread;
import Common.Utils.Utils_;
import _VisualDVM.Constants;
import _VisualDVM.Global;
import _VisualDVM.Repository.Server.DiagnosticSignalHandler;
import _VisualDVM.Repository.Server.ServerCode;
import _VisualDVM.Repository.Server.ServerExchangeUnit_2021;
import _VisualDVM.Utils;
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;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Properties;
import java.util.Vector;
public abstract class RepositoryServer<D extends Database> {
public final static String separator = "----------------------------------";
protected static FileWriter Log;
protected static boolean printOn = true;
//-
public D db;
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; //для отладки.
protected Thread interruptThread = new InterruptThread(10000,
() -> {
System.exit(0);
return null;
});
Class<D> d_class;
//-----------RECURSION ->
SignalHandler signalHandler = signal -> {
};
public RepositoryServer(Class<D> d_class_in) {
d_class = d_class_in;
}
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) {
if (printOn) {
try {
Log = new FileWriter("Log.txt", true);
String dmessage = Utils_.Brackets("SESSION -> ") + new Date() +
" " + message;
Log.write(dmessage + "\n");
Log.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
//-DVMTestingChecker
public abstract int getPort();
protected abstract void Session() throws Exception;
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");
props.put("mail.smtp.connectiontimeout", String.valueOf(Global.properties.SocketTimeout));
props.put("mail.smtp.timeout", String.valueOf(Global.properties.SocketTimeout));
props.put("mail.smtp.writetimeout", String.valueOf(Global.properties.SocketTimeout));
//------------------------------
LinkedHashMap<String, File> innerFiles = new LinkedHashMap<>();
for (String aName : message_in.files.keySet()) {
File f = Utils.getTempFileName(aName);
Utils_.bytesToFile(message_in.files.get(aName), f);
innerFiles.put(aName, f);
}
//------------------------------
Session session = Session.getDefaultInstance(props,
new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
Constants.MailAddress,
Constants.MailPassword);
}
});
boolean done = false;
int attempts = 5;
while (!done && (attempts > 0)) {
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);
done = true;
} catch (Exception ex) {
System.out.println("Исключение во время отправки сообщения абоненту " + Utils_.Brackets(address_in));
ex.printStackTrace();
Utils_.sleep(1000);
} finally {
attempts--;
}
}
} catch (Exception ex) {
System.out.println("Исключение во время выполнения рассылки.");
ex.printStackTrace();
}
});
thread.start();
}
public boolean canDelete(DBObject object) throws Exception {
return true;
}
public void StartAction() throws Exception {
}
public void Start() throws Exception {
/*
File started = new File(Constants.STARTED);
if (started.exists())
FileUtils.forceDelete(started);
Utils.createEmptyFile(Constants.STARTED);
*/
DiagnosticSignalHandler.install("TERM", signalHandler);
DiagnosticSignalHandler.install("INT", signalHandler);
DiagnosticSignalHandler.install("ABRT", signalHandler);
interruptThread.start();
startAdditionalThreads();
server = new ServerSocket(getPort());
StartAction();
while (true) {
try {
clientSocket = server.accept();
ResetLog();
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 = null;
Print("клиент_2021: <- " + (request.codeName));
try {
code = request.getCode();
//базовый функционал.
switch (code) {
//<editor-fold desc="файлы и почта">
case ReadFile:
Print("Отправить клиенту текст файла по пути " + Utils_.Brackets(request.arg));
response = new ServerExchangeUnit_2021(ServerCode.OK, "", Utils.ReadAllText(new File(request.arg)));
break;
case SendFile:
//нам пришел файл.
Print("Получить от клиента файл, и распаковать его по пути " + Utils_.Brackets(request.arg));
request.Unpack(); //распаковка идет по его аргу-пути назначения
response = new ServerExchangeUnit_2021(ServerCode.OK);
break;
case ReceiveFile:
Print("Отправить клиенту файл по пути " + Utils_.Brackets(request.arg));
response = new ServerExchangeUnit_2021(ServerCode.OK);
File file = new File(request.arg);
response.object = file.exists() ? Utils_.fileToBytes(file) : null;
break;
case Email:
Print("Отправка сообщения электронной почты");
Email((EmailMessage) request.object, request.arg);
response = new ServerExchangeUnit_2021(ServerCode.OK);
break;
case EmailBroadcast:
EmailBroadcast();
break;
//</editor-fold>
//<editor-fold desc="Главная база данных">
case CheckObjectExistense:
p = (Pair<Class, Object>) request.object;
Print("Проверить существование объекта класса " + p.getKey().toString() + " с ключом " + p.getValue());
response = new ServerExchangeUnit_2021(ServerCode.OK);
response.object = db.checkObjectExistense(p.getKey(), p.getValue());
break;
case EditObject:
DBObject new_object = (DBObject) request.object;
Print("Редактировать объект " + new_object.getPK());
db.UpdateWithCheck(new_object);
afterEditAction(new_object);
response = new ServerExchangeUnit_2021(ServerCode.OK);
break;
case DeleteObject: //устарело. потом убрать. сейчас на это баг репорты повязаны.
dbObject = (DBObject) request.object;
Print("Удалить объект " + dbObject.getPK());
db.DeleteWithCheck(dbObject);
afterDeleteAction(dbObject);
response = new ServerExchangeUnit_2021(ServerCode.OK);
break;
case GetObjectCopyByPK:
p = (Pair<Class, Object>) request.object;
Print("Получить копию объекта класса " + p.getKey().toString() + " по ключу " + p.getValue());
dbObject = db.getObjectCopyByPK(p.getKey(), p.getValue());
response = new ServerExchangeUnit_2021(ServerCode.OK);
response.object = dbObject;
break;
case GetObjectsCopiesByPK:
Print("Получить список копий объектов по ключам");
p = (Pair<Class, Object>) request.object;
response = new ServerExchangeUnit_2021(ServerCode.OK);
response.object = db.getObjectsCopies(p.getKey(), (Vector<Object>) p.getValue());
break;
case PublishObject:
PublishObject();
break;
case PublishObjects:
PublishObjects();
break;
case DeleteObjectByPK:
DeleteObjectByPK();
break;
case DeleteObjectsByPK:
DeleteObjectsByPK();
break;
case CloneObjectByPK:
CloneObject();
break;
//</editor-fold>
case EXIT:
Print("ЗАВЕРШИТЬ РАБОТУ СЕРВЕРА");
System.exit(0);
break;
case Ping:
Print("Проверка активности сервера");
Ping();
break;
default:
Session();
break;
}
} catch (Exception ex) {
response = new ServerExchangeUnit_2021(ServerCode.FAIL, "Исключение сервера", ex);
} finally {
Print("сервер: -> " + response.codeName);
out.writeObject(response);
Print("Ответ отправлен.");
}
}
Print("Соединение с клиентом завершено.");
//->
} catch (Exception ex) {
Print("Исключение.Соединение с клиентом завершено.");
} 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("Сервер ждет следующего клиента.");
}
}
}
private void EmailBroadcast() throws Exception {
String[] packed = request.arg.split("\n");
for (String address : packed) {
if (!address.isEmpty()) {
Email((EmailMessage) request.object, address);
}
}
response = new ServerExchangeUnit_2021(ServerCode.OK);
}
//--
protected Database getDefaultDatabase() {
return db;
}
//--
private void PublishObject() throws Exception {
response = new ServerExchangeUnit_2021(ServerCode.OK);
DBObject dbObject = (DBObject) request.object;
beforePublishAction(dbObject);
response.object = (Serializable) getDefaultDatabase().InsertS(dbObject).getPK();
afterPublishAction(dbObject);
}
private void PublishObjects() throws Exception {
response = new ServerExchangeUnit_2021(ServerCode.OK);
Vector<DBObject> objects = (Vector<DBObject>) request.object;
Database database = getDefaultDatabase();
for (DBObject dbObject : objects) {
beforePublishAction(dbObject);
response.object = (Serializable) database.InsertS(dbObject).getPK();
afterPublishAction(dbObject);
}
}
private void CloneObject() throws Exception {
response = new ServerExchangeUnit_2021(ServerCode.OK);
Print("Дублировать объект по ключу");
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();
}
}
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 {
}
//------------------------------
private void DeleteObjectByPK() throws Exception {
Print("Удалить объект по ключу");
Pair<Class, Object> to_delete = (Pair<Class, Object>) request.object;
afterDeleteAction(getDefaultDatabase().DeleteByPK(to_delete.getKey(), to_delete.getValue()));
response = new ServerExchangeUnit_2021(ServerCode.OK);
}
private void DeleteObjectsByPK() throws Exception {
Print("Удалить объекты по ключам");
Pair<Class, Vector<Object>> to_delete = (Pair<Class, Vector<Object>>) request.object;
Database database = getDefaultDatabase();
for (Object object : to_delete.getValue()) {
afterDeleteAction(database.DeleteByPK(to_delete.getKey(), object));
}
response = new ServerExchangeUnit_2021(ServerCode.OK);
}
public void afterDeleteAction(DBObject object) throws Exception {
}
public void Ping() {
response = new ServerExchangeUnit_2021(ServerCode.OK);
}
}