Files
VisualSapfor/src/_VisualDVM/Repository/Server/RepositoryServer.java
2025-02-18 16:21:20 +03:00

395 lines
17 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.Server;
import Common.Database.Database;
import Common.Database.Objects.DBObject;
import Common.Database.Objects.riDBObject;
import Common.Database.RepositoryRefuseException;
import Common.Utils.InterruptThread;
import Common.Utils.Utils_;
import _VisualDVM.Constants;
import _VisualDVM.Passes.Server.RepositoryPass;
import _VisualDVM.Repository.EmailMessage;
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> {
protected static FileWriter Log;
protected static boolean printOn = true;
public abstract String getServerFileName();
public abstract String getServerHomeName();
//-
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 void Session() throws Exception {};
protected void UnsafeSession() throws Exception {}
protected void startAdditionalThreads() {
}
public void ActivateDB() {
try {
db = d_class.newInstance();
db.Activate();
} 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(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);
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);
}
});
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();
}
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();
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 = 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 Email:
Email();
break;
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;
}
}
} 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("Сервер ждет следующего клиента.");
}
}
}
//--
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 void body() throws Exception {
try {
super.body();
success = true;
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
protected void ServerAction() throws Exception {
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 {
}
}