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 { 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_class; //-----------RECURSION -> SignalHandler signalHandler = signal -> { }; public RepositoryServer(Class 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 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 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 objects = (Vector) request.object; for (DBObject dbObject : objects) { beforePublishAction(dbObject); response.object = (Serializable) db.InsertS(dbObject).getPK(); afterPublishAction(dbObject); } } void CloneObject() throws Exception { Pair to_clone = (Pair) 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 p = (Pair) request.object; DBObject dbObject = db.getObjectCopyByPK(p.getKey(), p.getValue()); response.object = dbObject; } void GetObjectsCopiesByPK() throws Exception { Pair p = (Pair) request.object; response.object = db.getObjectsCopies(p.getKey(), (Vector) p.getValue()); } void EditObject() throws Exception { DBObject new_object = (DBObject) request.object; db.UpdateWithCheck(new_object); afterEditAction(new_object); } void DeleteObjectByPK() throws Exception { Pair to_delete = (Pair) request.object; afterDeleteAction(db.DeleteByPK(to_delete.getKey(), to_delete.getValue())); } void DeleteObjectsByPK() throws Exception { Pair> to_delete = (Pair>) 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 { } }