Files
VisualSapfor/src/Repository/RepositoryServer.java

358 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 Repository;
import Common.Constants;
import Common.Database.DBObject;
import Common.Database.Database;
import Common.Database.rDBObject;
import Common.Global;
import Common.Utils.InterruptThread;
import Common.Utils.Utils;
import Repository.Server.DiagnosticSignalHandler;
import Repository.Server.ServerCode;
import Repository.Server.ServerExchangeUnit_2021;
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,
() -> {
System.out.println("INTERRUPT FILE FOUND");
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);
}
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();
}
public boolean needsEmail(String email) {
return true;
}
public void PublishAction(DBObject object) throws Exception {
}
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) {
//<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.packFile(file) : null;
break;
case Email:
Print("Отправка сообщения электронной почты");
Email((EmailMessage) request.object);
response = new ServerExchangeUnit_2021(ServerCode.OK);
break;
//</editor-fold>
//<editor-fold desc="Главная база данных">
case PublishObject:
dbObject = (DBObject) request.object;
Print("Опубликовать объект " + dbObject.getPK());
db.InsertWithCheck(dbObject);
PublishAction(dbObject);
response = new ServerExchangeUnit_2021(ServerCode.OK);
response.object = (Serializable) dbObject.getPK();
break;
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:
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;
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 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 PublishAIObject:
dbObject = (DBObject) request.object;
Print("Опубликовать объект с автоинкрементным ключом");
db.Insert(dbObject); //проверка не нужна,АИ гарантирует что ключ уникален.
PublishAction(dbObject);
response = new ServerExchangeUnit_2021(ServerCode.OK);
response.object = (Serializable) dbObject.getPK(); //чтобы пользователь знал, какой ключ.
break;
//</editor-fold>
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 CopyAction(rDBObject src, rDBObject dst) throws Exception {
}
//--
}