Files
VisualSapfor/src/Repository/RepositoryServer.java

358 lines
19 KiB
Java
Raw Normal View History

2023-09-17 22:13:42 +03:00
package Repository;
2023-10-14 00:43:39 +03:00
import Common.Constants;
2023-09-17 22:13:42 +03:00
import Common.Database.DBObject;
import Common.Database.Database;
import Common.Database.iDBObject;
2023-09-17 22:13:42 +03:00
import Common.Global;
import Common.Utils.InterruptThread;
import Common.Utils.Utils;
import Repository.Server.DiagnosticSignalHandler;
import Repository.Server.ServerCode;
import Repository.Server.ServerExchangeUnit_2021;
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;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Properties;
import java.util.Vector;
public abstract class RepositoryServer<D extends Database> {
Class<D> d_class;
protected Socket clientSocket; //сокет для общения
protected ServerSocket server; // серверсокет
protected ObjectInputStream in; // поток чтения из сокета
protected ObjectOutputStream out; // поток записи в сокет
//-
public D db;
protected static FileWriter Log;
protected ServerExchangeUnit_2021 request;
protected ServerExchangeUnit_2021 response;
//-
protected ServerCode code;
protected long count = 0; //для отладки.
protected static boolean printOn = false;
//-----------
SignalHandler signalHandler = signal -> {
};
//------------
public abstract int getPort();
protected abstract void Session() throws Exception;
protected void startAdditionalThreads() {
}
public final static String separator = "----------------------------------";
public RepositoryServer(Class<D> d_class_in) {
d_class = d_class_in;
}
public void ActivateDB() {
try {
db = d_class.newInstance();
db.Connect();
db.CreateAllTables();
db.prepareTablesStatements();
db.Synchronize();
} catch (Exception ex) {
ex.printStackTrace();
}
}
protected Thread interruptThread = new InterruptThread(10000,
() -> {
2023-10-09 22:51:54 +03:00
System.out.println("INTERRUPT FILE FOUND");
2023-09-17 22:13:42 +03:00
System.exit(0);
return null;
});
protected static void Print(String message) throws IOException {
if (printOn) {
Log = new FileWriter("Log.txt", true);
String dmessage = Utils.Brackets("SESSION -> ") + new Date() +
" " + message;
System.out.println(dmessage);
Log.write(dmessage + "\n");
Log.close();
}
}
public void Email(EmailMessage message_in, File... directAttachements) throws Exception {
Thread thread = new Thread(() -> {
System.out.println("EMAIL THREAD STARTED");
try {
Properties props = new Properties();
props.put("mail.smtp.host", Global.properties.SMTPHost);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", String.valueOf(Global.properties.SMTPPort));
props.put("mail.smtp.socketFactory.port", String.valueOf(Global.properties.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.unpackFile(message_in.files.get(aName), f);
innerFiles.put(aName, f);
2023-09-17 22:13:42 +03:00
}
Vector<String> targets_ = new Vector<>();
targets_.add(Constants.MailAddress); //себе.
targets_.addAll(message_in.targets);
//------------------------------
Session session = Session.getDefaultInstance(props,
new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
Constants.MailAddress,
Constants.MailPassword);
}
});
for (String target : targets_) {
System.out.println("target=" + target);
if (needsEmail(target)) {
System.out.println("needs email");
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(target));
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);
}
for (File f : directAttachements) {
if (f.exists()) {
MimeBodyPart attachmentBodyPart = new MimeBodyPart();
DataSource source = new FileDataSource(f);
attachmentBodyPart.setDataHandler(new DataHandler(source));
attachmentBodyPart.setFileName(f.getName());
multipart.addBodyPart(attachmentBodyPart);
}
}
message.setContent(multipart);
Transport.send(message);
System.out.println("message sent");
done = true;
} catch (Exception ex) {
System.out.println("Исключение во время отправки сообщения абоненту " + Utils.Brackets(target));
ex.printStackTrace();
Utils.sleep(1000);
} finally {
attempts--;
}
}
} else System.out.println("does not need email");
}
} catch (Exception ex) {
System.out.println("Исключение во время выполнения рассылки.");
ex.printStackTrace();
}
System.out.println("EMAIL THREAD ENDED");
});
thread.start();
2023-09-17 22:13:42 +03:00
}
2023-10-09 22:51:54 +03:00
public boolean needsEmail(String email) {
2023-09-17 22:13:42 +03:00
return true;
}
public void beforePublishAction(DBObject object) throws Exception {
}
public void afterPublishAction(DBObject object) throws Exception {
2023-09-17 22:13:42 +03:00
}
public boolean canDelete(DBObject object) throws Exception {
return true;
}
public void DeleteAction(DBObject object) throws Exception {
}
public void StartAction() throws Exception {
}
public void Start() throws Exception {
DiagnosticSignalHandler.install("TERM", signalHandler);
DiagnosticSignalHandler.install("INT", signalHandler);
DiagnosticSignalHandler.install("ABRT", signalHandler);
interruptThread.start();
if (!Global.properties.OldServer)
startAdditionalThreads();
server = new ServerSocket(getPort());
Print("Сервер запущен!");
StartAction();
while (true) {
try {
clientSocket = server.accept();
Print((count++) + " клиент присоединился, IP=" + clientSocket.getInetAddress());
code = ServerCode.Undefined;
out = new ObjectOutputStream(clientSocket.getOutputStream());
in = new ObjectInputStream(clientSocket.getInputStream());
//->
while (true) {
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) {
2023-11-15 19:45:53 +03:00
//<editor-fold desc="файлы и почта">
2023-09-17 22:13:42 +03:00
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.packFile(file) : null;
break;
case Email:
Print("Отправка сообщения электронной почты");
Email((EmailMessage) request.object);
response = new ServerExchangeUnit_2021(ServerCode.OK);
break;
//</editor-fold>
2023-11-15 19:45:53 +03:00
//<editor-fold desc="Главная база данных">
2023-09-17 22:13:42 +03:00
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);
response = new ServerExchangeUnit_2021(ServerCode.OK);
break;
case DeleteObject: //устарело. потом убрать. сейчас на это баг репорты повязаны.
2023-09-17 22:13:42 +03:00
dbObject = (DBObject) request.object;
Print("Удалить объект " + dbObject.getPK());
db.DeleteWithCheck(dbObject);
DeleteAction(dbObject);
response = new ServerExchangeUnit_2021(ServerCode.OK);
break;
case DeleteObjectByPK:
Print("Удалить объект по ключу");
Pair<Class, Object> to_delete = (Pair<Class, Object>) request.object;
DeleteAction(db.DeleteByPK(to_delete.getKey(), to_delete.getValue()));
response = new ServerExchangeUnit_2021(ServerCode.OK);
break;
2023-09-17 22:13:42 +03:00
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;
2023-09-17 22:13:42 +03:00
case DeleteObjects:
Print("Удалить список объектов ");
Vector<Object> objects = (Vector<Object>) request.object;
db.BeginTransaction();
for (Object object : objects) {
dbObject = (DBObject) object;
if (canDelete(dbObject)) {
db.DeleteWithCheck(dbObject);
DeleteAction(dbObject);
}
}
db.Commit();
response = new ServerExchangeUnit_2021(ServerCode.OK);
break;
//------------------------
case PublishObject:
dbObject = (DBObject) request.object;
beforePublishAction(dbObject);
PublishObject(dbObject);
afterPublishAction(dbObject);
response = new ServerExchangeUnit_2021(ServerCode.OK);
response.object = (Serializable) dbObject.getPK();
break;
2023-11-15 19:45:53 +03:00
//</editor-fold>
2023-09-17 22:13:42 +03:00
case EXIT:
Print("ЗАВЕРШИТЬ РАБОТУ СЕРВЕРА");
System.exit(0);
break;
default:
Session();
break;
}
} catch (Exception ex) {
response = new ServerExchangeUnit_2021(ServerCode.FAIL, "Исключение сервера", ex);
} finally {
Print("сервер: -> " + response.codeName);
out.writeObject(response);
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("Сервер ждет следующего клиента.");
}
}
}
public void PublishObject(DBObject dbObject) throws Exception {
if (dbObject instanceof iDBObject) {
Print("Опубликовать объект");
db.Insert(dbObject);
} else {
Print("Опубликовать объект с автоинкрементным ключом");
db.InsertWithCheck(dbObject); //проверка не нужна,АИ гарантирует что ключ уникален.
}
2023-09-17 22:13:42 +03:00
}
}