Initial commit

This commit is contained in:
2025-10-16 12:29:15 +02:00
commit 2100aee601
14 changed files with 465 additions and 0 deletions

38
.gitignore vendored Normal file
View File

@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

3
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

7
.idea/encodings.xml generated Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>

14
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_22" default="true" project-jdk-name="22" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

25
pom.xml Normal file
View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cz.jzitnik</groupId>
<artifactId>MeitSort</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>22</maven.compiler.source>
<maven.compiler.target>22</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>jakarta.mail</artifactId>
<version>2.0.1</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,33 @@
package cz.jzitnik;
import cz.jzitnik.utils.mail.MailSender;
import jakarta.mail.Message;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class GlobalContext {
private final BlockingQueue<Message> blockingQueue = new LinkedBlockingQueue<>();
private final MailSender mailSender;
private boolean waitingForMessage = false;
public GlobalContext(MailSender mailSender) {
this.mailSender = mailSender;
}
public BlockingQueue<Message> getBlockingQueue() {
return blockingQueue;
}
public boolean isWaitingForMessage() {
return waitingForMessage;
}
public void setWaitingForMessage(boolean waitingForMessage) {
this.waitingForMessage = waitingForMessage;
}
public MailSender getMailSender() {
return mailSender;
}
}

View File

@ -0,0 +1,56 @@
package cz.jzitnik;
import cz.jzitnik.algs.BubbleSort;
import cz.jzitnik.utils.SortingAlgorithm;
import cz.jzitnik.utils.mail.MailContextPool;
import cz.jzitnik.utils.mail.MailSender;
import cz.jzitnik.utils.mail.read.MailReadHandler;
import cz.jzitnik.utils.mail.read.MailReader;
import jakarta.mail.MessagingException;
import jakarta.mail.PasswordAuthentication;
import java.io.IOException;
import java.util.Arrays;
import java.util.Properties;
public class Main {
private static MailContextPool getMailContextPool() {
Properties loginProps = new Properties();
loginProps.put("mail.smtp.auth", "true");
loginProps.put("mail.smtp.starttls.enable", "true");
loginProps.put("mail.smtp.host", "smtppro.zoho.eu");
loginProps.put("mail.smtp.port", "587");
loginProps.put("mail.store.protocol", "imaps");
loginProps.put("mail.imaps.host", "imappro.zoho.eu");
loginProps.put("mail.imaps.port", "993");
loginProps.put("mail.imaps.ssl.enable", "true");
return new MailContextPool(
loginProps,
new PasswordAuthentication("klindkubak@zohomail.eu", System.getenv("MEIT_PASSWORD"))
);
}
public static void main(String[] args) throws MessagingException, InterruptedException, IOException {
MailContextPool mailContextPool = getMailContextPool();
GlobalContext globalContext = new GlobalContext(
new MailSender(mailContextPool)
);
MailReader mailReader = new MailReader(mailContextPool, 1000, new MailReadHandler(globalContext));
Thread thread = new Thread(mailReader);
thread.start();
SortingAlgorithm sortingAlgorithm = new BubbleSort(globalContext, "klindkubak@zohomail.eu", "sefljulie@zohomail.eu");
int[] arr = {3, 2, 1};
int[] newArr = sortingAlgorithm.sort(arr);
System.out.println(Arrays.toString(newArr));
System.exit(0);
}
}

View File

@ -0,0 +1,28 @@
package cz.jzitnik.algs;
import cz.jzitnik.GlobalContext;
import cz.jzitnik.utils.SortingAlgorithm;
import jakarta.mail.MessagingException;
import java.io.IOException;
public class BubbleSort extends SortingAlgorithm {
public BubbleSort(GlobalContext globalContext, String from, String recipient) {
super(globalContext, from, recipient);
}
public int[] sort(int[] arr) throws MessagingException, InterruptedException, IOException {
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1 - i; j++) {
if (compare(arr[j], arr[j + 1]) == ResponseAnswer.FIRST) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
}

View File

@ -0,0 +1,96 @@
package cz.jzitnik.utils;
import cz.jzitnik.GlobalContext;
import cz.jzitnik.utils.mail.MailSender;
import jakarta.mail.BodyPart;
import jakarta.mail.Message;
import jakarta.mail.MessagingException;
import jakarta.mail.Multipart;
import jakarta.mail.internet.InternetAddress;
import java.awt.geom.RectangularShape;
import java.io.IOException;
public abstract class SortingAlgorithm {
private final GlobalContext globalContext;
private final String from;
private final String recipient;
protected enum ResponseAnswer {
FIRST,
SECOND,
SAME,
}
public SortingAlgorithm(GlobalContext globalContext, String from, String recipient) {
this.globalContext = globalContext;
this.from = from;
this.recipient = recipient;
}
protected ResponseAnswer compare(int x, int y) throws MessagingException, InterruptedException, IOException {
System.out.println("Sending email");
MailSender mailSender = globalContext.getMailSender();
mailSender.sendMessage(
new InternetAddress(from),
InternetAddress.parse(recipient),
"Porovnání dvou čísel",
"Které číslo je větší? " + x + " nebo " + y + "? Pokud první odpovězte na email s textem PRVNI, pokud druhé tak DRUHE a pokud se rovnají odpovězte ROVNO."
);
globalContext.setWaitingForMessage(true);
System.out.println("Waiting for response");
Message answer = globalContext.getBlockingQueue().take();
globalContext.setWaitingForMessage(false);
String answ = getTextFromMessage(answer).trim();
if (answ.startsWith("PRVNI")) {
return ResponseAnswer.FIRST;
}
if (answ.startsWith("DRUHE")) {
return ResponseAnswer.SECOND;
}
if (answ.startsWith("ROVNO")) {
return ResponseAnswer.SAME;
}
return ResponseAnswer.FIRST;
}
public abstract int[] sort(int[] arr) throws MessagingException, InterruptedException, IOException;
private String getTextFromMessage(Message message) throws MessagingException, IOException {
Object content = message.getContent();
if (content instanceof String) {
// Plain text email
return (String) content;
} else if (content instanceof Multipart) {
Multipart multipart = (Multipart) content;
return getTextFromMultipart(multipart);
}
return "";
}
private String getTextFromMultipart(Multipart multipart) throws MessagingException, IOException {
for (int i = 0; i < multipart.getCount(); i++) {
BodyPart part = multipart.getBodyPart(i);
if (part.isMimeType("text/plain")) {
return (String) part.getContent();
} else if (part.getContent() instanceof Multipart) {
// Nested multipart
String result = getTextFromMultipart((Multipart) part.getContent());
if (!result.isEmpty()) {
return result;
}
}
}
return "";
}
}

View File

@ -0,0 +1,35 @@
package cz.jzitnik.utils.mail;
import jakarta.mail.PasswordAuthentication;
import jakarta.mail.Session;
import java.util.Properties;
public class MailContextPool {
private final Session session;
private final PasswordAuthentication passwordAuthentication;
private final Properties props;
public MailContextPool(Properties properties, PasswordAuthentication passwordAuthentication) {
session = Session.getInstance(properties,
new jakarta.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return passwordAuthentication;
}
});
this.passwordAuthentication = passwordAuthentication;
props = properties;
}
public Session getSession() {
return session;
}
public PasswordAuthentication getPasswordAuthentication() {
return passwordAuthentication;
}
public Properties getProps() {
return props;
}
}

View File

@ -0,0 +1,22 @@
package cz.jzitnik.utils.mail;
import jakarta.mail.Message;
import jakarta.mail.MessagingException;
import jakarta.mail.Transport;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeMessage;
public record MailSender(MailContextPool mailContextPool) {
public void sendMessage(InternetAddress from, InternetAddress[] to, String subject, String text) throws MessagingException {
Message message = new MimeMessage(mailContextPool.getSession());
message.setFrom(from);
message.setRecipients(
Message.RecipientType.TO,
to
);
message.setSubject(subject);
message.setText(text);
Transport.send(message);
}
}

View File

@ -0,0 +1,25 @@
package cz.jzitnik.utils.mail.read;
import cz.jzitnik.GlobalContext;
import jakarta.mail.Message;
public class MailReadHandler implements MailReader.OnNewEmailListener {
private final GlobalContext globalContext;
public MailReadHandler(GlobalContext globalContext) {
this.globalContext = globalContext;
}
@Override
public void onNewEmail(Message message) {
if (!globalContext.isWaitingForMessage()) {
return;
}
try {
globalContext.getBlockingQueue().put(message);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,77 @@
package cz.jzitnik.utils.mail.read;
import cz.jzitnik.utils.mail.MailContextPool;
import jakarta.mail.*;
import java.util.*;
public class MailReader implements Runnable {
private final MailContextPool pool;
private final String username;
private final String password;
private final long checkIntervalMs;
private final OnNewEmailListener listener;
private int lastMessageCount = 0;
public interface OnNewEmailListener {
void onNewEmail(Message message);
}
public MailReader(MailContextPool mailContextPool, long checkIntervalMs, OnNewEmailListener listener) {
this.pool = mailContextPool;
this.username = mailContextPool.getPasswordAuthentication().getUserName();
this.password = mailContextPool.getPasswordAuthentication().getPassword();
this.checkIntervalMs = checkIntervalMs;
this.listener = listener;
}
@Override
public void run() {
while (true) {
Store store = null;
Folder inbox = null;
try {
store = pool.getSession().getStore("imaps");
store.connect(pool.getProps().getProperty("mail.imaps.host"), username, password);
inbox = store.getFolder("INBOX");
inbox.open(Folder.READ_ONLY);
System.out.println("[EmailChecker] Connected and monitoring inbox...");
while (true) {
Message[] messages = inbox.getMessages();
int messageCount = messages.length;
if (messageCount > lastMessageCount) {
for (int i = lastMessageCount; i < messageCount; i++) {
Message newMessage = messages[i];
listener.onNewEmail(newMessage);
}
lastMessageCount = messageCount;
}
Thread.sleep(checkIntervalMs);
}
} catch (Exception e) {
System.err.println("[EmailChecker] Error: " + e.getMessage());
e.printStackTrace();
// Wait before retrying connection
try {
Thread.sleep(30_000); // wait 30 seconds before reconnecting
} catch (InterruptedException ignored) {
}
} finally {
try {
if (inbox != null && inbox.isOpen()) inbox.close(false);
if (store != null && store.isConnected()) store.close();
} catch (MessagingException ignored) {
}
}
}
}
}