diff --git a/OWNER.md b/OWNER.md
new file mode 100644
index 0000000..ba42dad
--- /dev/null
+++ b/OWNER.md
@@ -0,0 +1 @@
+Кудрявцев Дмитрий Вальтерович
diff --git a/config.xml b/config.xml
index 7d4cac2..75c54c2 100644
--- a/config.xml
+++ b/config.xml
@@ -1,16 +1,12 @@
-
-
+
+
-
-
+
+
-
-
-
-
diff --git a/pom.xml b/pom.xml
index f822ba6..b28dea2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,7 +28,7 @@
exec-maven-plugin
1.4.0
- arhangel.dim.lections.jdbc.JdbcExample
+ arhangel.dim.core.jdbc.DataBaseOrganizer
diff --git a/src/main/java/arhangel/dim/client/Client.java b/src/main/java/arhangel/dim/client/Client.java
deleted file mode 100644
index f9daeea..0000000
--- a/src/main/java/arhangel/dim/client/Client.java
+++ /dev/null
@@ -1,195 +0,0 @@
-package arhangel.dim.client;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.Socket;
-import java.util.Arrays;
-import java.util.Scanner;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import arhangel.dim.container.Container;
-import arhangel.dim.container.InvalidConfigurationException;
-import arhangel.dim.core.messages.Message;
-import arhangel.dim.core.messages.TextMessage;
-import arhangel.dim.core.messages.Type;
-import arhangel.dim.core.net.ConnectionHandler;
-import arhangel.dim.core.net.Protocol;
-import arhangel.dim.core.net.ProtocolException;
-
-/**
- * Клиент для тестирования серверного приложения
- */
-public class Client implements ConnectionHandler {
-
- /**
- * Механизм логирования позволяет более гибко управлять записью данных в лог (консоль, файл и тд)
- * */
- static Logger log = LoggerFactory.getLogger(Client.class);
-
- /**
- * Протокол, хост и порт инициализируются из конфига
- *
- * */
- private Protocol protocol;
- private int port;
- private String host;
-
- /**
- * Тред "слушает" сокет на наличие входящих сообщений от сервера
- */
- private Thread socketThread;
-
- /**
- * С каждым сокетом связано 2 канала in/out
- */
- private InputStream in;
- private OutputStream out;
-
- public Protocol getProtocol() {
- return protocol;
- }
-
- public void setProtocol(Protocol protocol) {
- this.protocol = protocol;
- }
-
- public int getPort() {
- return port;
- }
-
- public void setPort(int port) {
- this.port = port;
- }
-
- public String getHost() {
- return host;
- }
-
- public void setHost(String host) {
- this.host = host;
- }
-
- public void initSocket() throws IOException {
- Socket socket = new Socket(host, port);
- in = socket.getInputStream();
- out = socket.getOutputStream();
-
- /**
- * Инициализируем поток-слушатель. Синтаксис лямбды скрывает создание анонимного класса Runnable
- */
- socketThread = new Thread(() -> {
- final byte[] buf = new byte[1024 * 64];
- log.info("Starting listener thread...");
- while (!Thread.currentThread().isInterrupted()) {
- try {
- // Здесь поток блокируется на ожидании данных
- int read = in.read(buf);
- if (read > 0) {
-
- // По сети передается поток байт, его нужно раскодировать с помощью протокола
- Message msg = protocol.decode(Arrays.copyOf(buf, read));
- onMessage(msg);
- }
- } catch (Exception e) {
- log.error("Failed to process connection: {}", e);
- e.printStackTrace();
- Thread.currentThread().interrupt();
- }
- }
- });
-
- socketThread.start();
- }
-
- /**
- * Реагируем на входящее сообщение
- */
- @Override
- public void onMessage(Message msg) {
- log.info("Message received: {}", msg);
- }
-
- /**
- * Обрабатывает входящую строку, полученную с консоли
- * Формат строки можно посмотреть в вики проекта
- */
- public void processInput(String line) throws IOException, ProtocolException {
- String[] tokens = line.split(" ");
- log.info("Tokens: {}", Arrays.toString(tokens));
- String cmdType = tokens[0];
- switch (cmdType) {
- case "/login":
- // TODO: реализация
- break;
- case "/help":
- // TODO: реализация
- break;
- case "/text":
- // FIXME: пример реализации для простого текстового сообщения
- TextMessage sendMessage = new TextMessage();
- sendMessage.setType(Type.MSG_TEXT);
- sendMessage.setText(tokens[1]);
- send(sendMessage);
- break;
- // TODO: implement another types from wiki
-
- default:
- log.error("Invalid input: " + line);
- }
- }
-
- /**
- * Отправка сообщения в сокет клиент -> сервер
- */
- @Override
- public void send(Message msg) throws IOException, ProtocolException {
- log.info(msg.toString());
- out.write(protocol.encode(msg));
- out.flush(); // принудительно проталкиваем буфер с данными
- }
-
- @Override
- public void close() {
- // TODO: написать реализацию. Закройте ресурсы и остановите поток-слушатель
- }
-
- public static void main(String[] args) throws Exception {
-
- Client client = null;
- // Пользуемся механизмом контейнера
- try {
- Container context = new Container("client.xml");
- client = (Client) context.getByName("client");
- } catch (InvalidConfigurationException e) {
- log.error("Failed to create client", e);
- return;
- }
- try {
- client.initSocket();
-
- // Цикл чтения с консоли
- Scanner scanner = new Scanner(System.in);
- System.out.println("$");
- while (true) {
- String input = scanner.nextLine();
- if ("q".equals(input)) {
- return;
- }
- try {
- client.processInput(input);
- } catch (ProtocolException | IOException e) {
- log.error("Failed to process user input", e);
- }
- }
- } catch (Exception e) {
- log.error("Application failed.", e);
- } finally {
- if (client != null) {
- client.close();
- }
- }
- }
-}
diff --git a/src/main/java/arhangel/dim/client/ClientMain.java b/src/main/java/arhangel/dim/client/ClientMain.java
new file mode 100644
index 0000000..5db09f9
--- /dev/null
+++ b/src/main/java/arhangel/dim/client/ClientMain.java
@@ -0,0 +1,111 @@
+package arhangel.dim.client;
+
+import arhangel.dim.container.Container;
+import arhangel.dim.container.beans.WebConnection;
+import arhangel.dim.core.message.Message;
+
+import java.io.BufferedReader;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.InputStreamReader;
+import java.net.Socket;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+
+public class ClientMain {
+
+ private Socket socket;
+
+ private DataInputStream in;
+ private DataOutputStream out;
+
+ /**
+ * Нить, отвечающая за получение сообщений от сервера
+ */
+ private Thread listenThread;
+
+ /**
+ * Нить, отвечающая за отправку сообщений на сервер
+ */
+ private Thread writeThread;
+
+ /**
+ * Очередь, для обмена сообщений для отправки между главной нитью и writeThread
+ */
+ private BlockingQueue messagesToWrite;
+
+ /**
+ * Классы, отвечающие за работу нитей
+ */
+ private MessageListener listener;
+ private MessageWriter writer;
+
+ public ClientMain() {
+ }
+
+ public void init() {
+ try {
+ Container container = new Container("C:\\Users\\Дмитрий\\Documents\\technotrack\\java\\messenger\\config.xml");
+ WebConnection portAndHost = (WebConnection)container.getByClass("arhangel.dim.container.beans.WebConnection");
+ int port = portAndHost.getPort();
+ String host = portAndHost.getHost();
+ socket = new Socket(host, port);
+ in = new DataInputStream(socket.getInputStream());
+ out = new DataOutputStream(socket.getOutputStream());
+ messagesToWrite = new ArrayBlockingQueue<>(10);
+ listener = new MessageListener(in);
+ writer = new MessageWriter(out, messagesToWrite);
+ listenThread = new Thread(listener);
+ writeThread = new Thread(writer);
+ listenThread.start();
+ writeThread.start();
+ } catch (Exception e) {
+ System.err.println("Client initialization: exception caught: " + e.toString());
+ }
+ }
+
+ public void handleUserCommands() throws Exception {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
+ String line;
+ while (true) {
+ line = reader.readLine();
+ Message writeMessage;
+ if (line.startsWith("/")) {
+ writeMessage = new Message();
+ writeMessage.setMessage(line);
+ messagesToWrite.put(writeMessage);
+ if (line.equals("/exit")) {
+ System.out.println("Closing..");
+ stopThreads();
+ break;
+ }
+ } else {
+ writeMessage = new Message();
+ writeMessage.setMessage(line);
+ messagesToWrite.put(writeMessage);
+ }
+ }
+ }
+
+ public void stopThreads() {
+ try {
+ listenThread.interrupt();
+ writeThread.interrupt();
+ // join
+ } catch (Exception e) {
+ System.err.println("Failed to stop threads " + e.toString());
+ } finally {
+ IoUtil.closeQuietly(socket);
+ }
+ }
+
+ public static void main(String[] args) {
+ ClientMain threadedClient = new ClientMain();
+ threadedClient.init();
+ try {
+ threadedClient.handleUserCommands();
+ } catch (Exception e) {
+ System.err.println("Client: exception caught: " + e.toString());
+ }
+ }
+}
diff --git a/src/main/java/arhangel/dim/lections/socket/IoUtil.java b/src/main/java/arhangel/dim/client/IoUtil.java
similarity index 91%
rename from src/main/java/arhangel/dim/lections/socket/IoUtil.java
rename to src/main/java/arhangel/dim/client/IoUtil.java
index dcb4176..1766d38 100644
--- a/src/main/java/arhangel/dim/lections/socket/IoUtil.java
+++ b/src/main/java/arhangel/dim/client/IoUtil.java
@@ -1,4 +1,4 @@
-package arhangel.dim.lections.socket;
+package arhangel.dim.client;
import java.io.Closeable;
diff --git a/src/main/java/arhangel/dim/client/MessageListener.java b/src/main/java/arhangel/dim/client/MessageListener.java
new file mode 100644
index 0000000..3a9e1b6
--- /dev/null
+++ b/src/main/java/arhangel/dim/client/MessageListener.java
@@ -0,0 +1,65 @@
+package arhangel.dim.client;
+
+import arhangel.dim.core.message.AnswerMessage;
+import arhangel.dim.core.message.Protocol;
+import arhangel.dim.core.message.SerializationProtocol;
+
+import java.io.DataInputStream;
+
+/**
+ * Класс, получающий сообщения от сервера
+ */
+public class MessageListener implements Runnable {
+ private DataInputStream reader;
+
+ /**
+ * Протокол кодирования
+ */
+ private Protocol readProtocol;
+
+ public MessageListener(DataInputStream reader) {
+ this.reader = reader;
+ readProtocol = new SerializationProtocol<>();
+ }
+
+ @Override
+ public void run() {
+ try {
+ while (!Thread.currentThread().isInterrupted()) {
+ byte[] buf = new byte[1024 * 60];
+ int readSize = reader.read(buf);
+ if (readSize > 0) {
+ AnswerMessage answer = readProtocol.decode(buf);
+ handleAnswer(answer);
+ }
+ }
+ } catch (Exception e) {
+ System.err.println("Listener: exception caught: " + e.toString());
+ }
+ }
+
+ public void handleAnswer(AnswerMessage answer) throws Exception {
+ AnswerMessage.Value type = answer.getResult();
+ String message = answer.getMessage();
+ switch (type) {
+ case SUCCESS:
+ System.out.println(message);
+ break;
+ case ERROR:
+ System.out.println("Error:");
+ System.out.println(message);
+ break;
+ case LOGIN:
+ System.out.println("Error:\nPlease login first");
+ break;
+ case NUM_ARGS:
+ System.out.println("Error:\nWrong number of arguments");
+ break;
+ case CHAT:
+ System.out.println(message);
+ break;
+ default:
+ break;
+ }
+ }
+}
diff --git a/src/main/java/arhangel/dim/client/MessageWriter.java b/src/main/java/arhangel/dim/client/MessageWriter.java
new file mode 100644
index 0000000..1f2f6bd
--- /dev/null
+++ b/src/main/java/arhangel/dim/client/MessageWriter.java
@@ -0,0 +1,39 @@
+package arhangel.dim.client;
+
+import arhangel.dim.core.message.Message;
+import arhangel.dim.core.message.Protocol;
+import arhangel.dim.core.message.SerializationProtocol;
+
+import java.io.DataOutputStream;
+import java.util.concurrent.BlockingQueue;
+
+/**
+ * Класс, отправляющий сообщения серверу
+ */
+
+public class MessageWriter implements Runnable {
+
+ private DataOutputStream out;
+ private BlockingQueue messagesToWrite;
+
+ private Protocol writeProtocol;
+
+ public MessageWriter(DataOutputStream out, BlockingQueue messagesToWrite) {
+ this.out = out;
+ this.messagesToWrite = messagesToWrite;
+ writeProtocol = new SerializationProtocol<>();
+ }
+
+ @Override
+ public void run() {
+ try {
+ while (!Thread.currentThread().isInterrupted()) {
+ Message messageToWrite = messagesToWrite.take();
+ out.write(writeProtocol.encode(messageToWrite));
+ out.flush();
+ }
+ } catch (Exception e) {
+ System.err.println("MessageWriter: exception caught " + e.toString());
+ }
+ }
+}
diff --git a/src/main/java/arhangel/dim/container/Bean.java b/src/main/java/arhangel/dim/container/Bean.java
index 34b8f1e..4ed7463 100644
--- a/src/main/java/arhangel/dim/container/Bean.java
+++ b/src/main/java/arhangel/dim/container/Bean.java
@@ -49,4 +49,4 @@ public String toString() {
", properties=" + properties +
'}';
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/arhangel/dim/container/BeanGraph.java b/src/main/java/arhangel/dim/container/BeanGraph.java
index 306c0e6..3c44915 100644
--- a/src/main/java/arhangel/dim/container/BeanGraph.java
+++ b/src/main/java/arhangel/dim/container/BeanGraph.java
@@ -1,50 +1,154 @@
package arhangel.dim.container;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-/**
- *
- */
public class BeanGraph {
- // Граф представлен в виде списка связности для каждой вершины
+ // Граф представляем в виде списка связности
private Map> vertices = new HashMap<>();
+ private Map used;
+ private Map left; //вершины из которых вышли в dfs
+ private List answerForSort;
+
+ public BeanGraph() {
+ }
+
+ public BeanGraph(List beans) {
+ beans.forEach(this::addVertex);
+ }
/**
* Добавить вершину в граф
+ *
* @param value - объект, привязанный к вершине
*/
public BeanVertex addVertex(Bean value) {
- return null;
+ BeanVertex beanVertex = new BeanVertex(value);
+ if (vertices.containsKey(beanVertex)) {
+ return beanVertex;
+ }
+ vertices.put(beanVertex, new ArrayList<>());
+
+ //добавляем ребра в новую вершину (т.к порядок добавления может быть рандомным и пердыдущие вершины ждут эту
+ for (BeanVertex tmp : vertices.keySet()) {
+ for (Property property : tmp.getBean().getProperties().values()) {
+ if (property.getType() == ValueType.REF && property.getValue().equals(value.getName())) {
+ addEdge(tmp, beanVertex);
+ }
+ }
+ }
+
+ //добавляем ребра из новой вершины
+ for (Property property : value.getProperties().values()) {
+ if (property.getType() == ValueType.REF) {
+ for (BeanVertex tmp : vertices.keySet()) {
+ if (tmp.getBean().getName().equals(property.getValue())) {
+ addEdge(beanVertex, tmp);
+ }
+ }
+ }
+ }
+ return beanVertex;
}
/**
* Соединить вершины ребром
+ *
* @param from из какой вершины
- * @param to в какую вершину
+ * @param to в какую вершину
*/
- public void addEdge(BeanVertex from ,BeanVertex to) {
+ public void addEdge(BeanVertex from, BeanVertex to) {
+ List beanVertexes = getLinked(from);
+ if (beanVertexes.contains(to)) {
+ return;
+ }
+ beanVertexes.add(to);
}
/**
* Проверяем, связаны ли вершины
*/
public boolean isConnected(BeanVertex v1, BeanVertex v2) {
- return false;
+ return getLinked(v1).contains(v2);
}
/**
* Получить список вершин, с которыми связана vertex
*/
public List getLinked(BeanVertex vertex) {
- return null;
+ return vertices.get(vertex);
}
/**
* Количество вершин в графе
*/
public int size() {
- return 0;
+ return vertices.size();
+ }
+
+ /**
+ * Проверка на отсутствие циклов
+ */
+ public boolean checkCycle() {
+ used = new HashMap<>();
+ left = new HashMap<>();
+ for (BeanVertex tmp : vertices.keySet()) {
+ used.put(tmp, false);
+ left.put(tmp, false);
+ }
+ for (BeanVertex tmp : vertices.keySet()) {
+ if (!used.get(tmp)) {
+ if (dfsCheck(tmp)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ public List topSort() {
+ answerForSort = new ArrayList<>();
+ used = new HashMap<>();
+ for (BeanVertex tmp : vertices.keySet()) {
+ used.put(tmp, false);
+ }
+ for (BeanVertex tmp : vertices.keySet()) {
+ if (!used.get(tmp)) {
+ dfs(tmp);
+ }
+ }
+ ArrayList reverseAnswer = new ArrayList<>();
+ for (int i = 0; i < size(); ++i) {
+ reverseAnswer.add(answerForSort.get(i));
+ }
+
+ return reverseAnswer;
+ }
+
+ private void dfs(BeanVertex tmp) {
+ used.put(tmp, true);
+ for (BeanVertex nextBean : getLinked(tmp)) {
+ if (!used.get(nextBean)) {
+ dfs(nextBean);
+ }
+ }
+ answerForSort.add(tmp);
+ }
+
+ // Проверка на то, есть ли цикл из этой вершины
+ private boolean dfsCheck(BeanVertex tmp) {
+ used.put(tmp, true);
+ for (BeanVertex nextBean : getLinked(tmp)) {
+ if (used.get(nextBean) && !left.get(nextBean)) {
+ return true;
+ }
+ if (!used.get(nextBean) && dfsCheck(nextBean)) {
+ return true;
+ }
+ }
+ left.put(tmp, true);
+ return false;
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/arhangel/dim/container/BeanVertex.java b/src/main/java/arhangel/dim/container/BeanVertex.java
index 1fbd084..3f746a2 100644
--- a/src/main/java/arhangel/dim/container/BeanVertex.java
+++ b/src/main/java/arhangel/dim/container/BeanVertex.java
@@ -17,4 +17,4 @@ public Bean getBean() {
public void setBean(Bean bean) {
this.bean = bean;
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/arhangel/dim/container/BeanXmlReader.java b/src/main/java/arhangel/dim/container/BeanXmlReader.java
index 3350f1e..d37347d 100644
--- a/src/main/java/arhangel/dim/container/BeanXmlReader.java
+++ b/src/main/java/arhangel/dim/container/BeanXmlReader.java
@@ -1,10 +1,24 @@
package arhangel.dim.container;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import javax.naming.NameNotFoundException;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+
-/**
- *
- */
public class BeanXmlReader {
private static final String TAG_BEAN = "bean";
private static final String TAG_PROPERTY = "property";
@@ -14,8 +28,47 @@ public class BeanXmlReader {
private static final String ATTR_BEAN_ID = "id";
private static final String ATTR_BEAN_CLASS = "class";
- public List parseBeans(String pathToFile) {
- return null;
- }
+ public static List parseBeans(String pathToFile) throws IOException, ParserConfigurationException, SAXException,
+ NameNotFoundException {
+ List parseResult = new ArrayList<>();
+ File inputXmlFile = Utils.initFile(pathToFile);
+ if (!inputXmlFile.exists()) {
+ throw new FileNotFoundException("Incorrect input file");
+ }
+
+ DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
+ Document xmlDocument = documentBuilder.parse(inputXmlFile);
+ NodeList listOfBeanNodes = xmlDocument.getElementsByTagName(TAG_BEAN);
+
+ //поочередно разбираем данные о bean
+ for (int i = 0; i < listOfBeanNodes.getLength(); ++i) {
+ Node node = listOfBeanNodes.item(i);
+ Element nextElement = (Element) node;
+ NodeList propertiesList = nextElement.getElementsByTagName(TAG_PROPERTY);
+ Map properties = new HashMap<>();
-}
+ //парсим properties
+ for (int j = 0; j < propertiesList.getLength(); ++j) {
+ Element nextProperty = (Element) propertiesList.item(j);
+ String name = nextProperty.getAttribute(ATTR_NAME);
+ Property nextValue;
+ if (nextProperty.hasAttribute(ATTR_VALUE)) {
+ nextValue = new Property(name, nextProperty.getAttribute(ATTR_VALUE), ValueType.VAL);
+ } else if (nextProperty.hasAttribute(ATTR_REF)) {
+ nextValue = new Property(name, nextProperty.getAttribute(ATTR_REF), ValueType.REF);
+ } else {
+ throw new NameNotFoundException("Incorrect name of attribute");
+ }
+ properties.put(name, nextValue);
+
+ }
+
+ Bean nextBean = new Bean(nextElement.getAttribute(ATTR_BEAN_ID), nextElement.getAttribute(ATTR_BEAN_CLASS),
+ properties);
+ parseResult.add(nextBean);
+ }
+
+ return parseResult;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/arhangel/dim/container/Container.java b/src/main/java/arhangel/dim/container/Container.java
index 4213396..36a6799 100644
--- a/src/main/java/arhangel/dim/container/Container.java
+++ b/src/main/java/arhangel/dim/container/Container.java
@@ -1,28 +1,106 @@
package arhangel.dim.container;
+import org.xml.sax.SAXException;
+
+import javax.naming.NameNotFoundException;
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+
-/**
- * Используйте ваш xml reader чтобы прочитать конфиг и получить список бинов
- */
public class Container {
private List beans;
+ private Map objectByName;
+ private Map objectByClassName;
/**
- * Если не получается считать конфиг, то бросьте исключение
- * @throws InvalidConfigurationException неверный конфиг
+ * @throws arhangel.dim.container.InvalidConfigurationException - неверный конфиг
*/
public Container(String pathToConfig) throws InvalidConfigurationException {
+ objectByClassName = new HashMap<>();
+ objectByName = new HashMap<>();
+ List beansFromXml;
+ try {
+ beansFromXml = BeanXmlReader.parseBeans(pathToConfig);
+ } catch (IOException e) {
+ throw new InvalidConfigurationException(e.getMessage());
+ } catch (ParserConfigurationException e) {
+ throw new InvalidConfigurationException("Can't parse configuration." + e.getMessage());
+ } catch (SAXException e) {
+ throw new InvalidConfigurationException("SAX parse exception." + e.getMessage());
+ } catch (NameNotFoundException e) {
+ throw new InvalidConfigurationException("File does not exist." + e.getMessage());
+ }
+ List tmp = (new BeanGraph(beansFromXml).topSort());
+ beans = new ArrayList<>();
+ for (BeanVertex beanVertex : tmp) {
+ beans.add(beanVertex.getBean());
+ }
+ init(beans);
+ }
+
+ private void init(List beans) {
+ for (int i = 0; i < beans.size(); ++i) {
+ initBean(beans.get(i));
+ }
+ }
+
+ private void initBean(Bean bean) {
+ String name = bean.getClassName();
+ Class clazz;
+ try {
+ clazz = Class.forName(name);
+ } catch (ClassNotFoundException e) {
+ System.err.println("Incorrect name of class " + e.getMessage());
+ return;
+ }
+
+ // Создаём объект нужного нам класса
+ Object object;
+ try {
+ object = clazz.newInstance();
+ } catch (InstantiationException e) {
+ System.err.println("Can't initialize class " + e.getMessage());
+ return;
+ } catch (IllegalAccessException e) {
+ System.err.print(e.getMessage());
+ return;
+ }
+
+ // Создаём и применяем к нему методы для установки нужных значений
+ for (Property property : bean.getProperties().values()) {
+ String methodName = "set" + Utils.capitalize(property.getName());
+ try {
+ if (property.getType() == ValueType.REF) {
+ Object parameter = getByName(property.getValue());
+ Method method = clazz.getMethod(methodName,
+ parameter.getClass());
+ method.invoke(object, parameter);
+ } else {
+ Method method = clazz.getMethod(methodName,
+ int.class);
+ method.invoke(object, new Integer(property.getValue()));
+ }
+ } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
+ System.err.println(e.getMessage());
+ }
+ }
+ objectByClassName.put(bean.getClassName(), object);
+ objectByName.put(bean.getName(), object);
- // вызываем BeanXmlReader
}
/**
- * Вернуть объект по имени бина из конфига
- * Например, Car car = (Car) container.getByName("carBean")
+ * Вернуть объект по имени бина из конфига
+ * Например, Car car = (Car) container.getByName("carBean")
*/
public Object getByName(String name) {
- return null;
+ return objectByName.get(name);
}
/**
@@ -30,35 +108,7 @@ public Object getByName(String name) {
* Например, Car car = (Car) container.getByClass("arhangel.dim.container.Car")
*/
public Object getByClass(String className) {
- return null;
- }
-
- private void instantiateBean(Bean bean) {
-
- /*
- // Примерный ход работы
-
- String className = bean.getClassName();
- Class clazz = Class.forName(className);
- // ищем дефолтный конструктор
- Object ob = clazz.newInstance();
-
-
- for (String name : bean.getProperties().keySet()) {
- // ищем поле с таким именен внутри класса
- // учитывая приватные
- Field field = clazz.getDeclaredField(name);
- // проверяем, если такого поля нет, то кидаем InvalidConfigurationException с описание ошибки
-
- // Делаем приватные поля доступными
- field.setAccessible(true);
-
- // Далее определяем тип поля и заполняем его
- // Если поле - примитив, то все просто
- // Если поле ссылка, то эта ссылка должа была быть инициализирована ранее
-
- */
-
+ return objectByClassName.get(className);
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/arhangel/dim/container/CycleReferenceException.java b/src/main/java/arhangel/dim/container/CycleReferenceException.java
index 14edb65..a274377 100644
--- a/src/main/java/arhangel/dim/container/CycleReferenceException.java
+++ b/src/main/java/arhangel/dim/container/CycleReferenceException.java
@@ -7,4 +7,4 @@ public class CycleReferenceException extends Exception {
public CycleReferenceException(String message) {
super(message);
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/arhangel/dim/container/Messenger.java b/src/main/java/arhangel/dim/container/Messenger.java
new file mode 100644
index 0000000..cb4b575
--- /dev/null
+++ b/src/main/java/arhangel/dim/container/Messenger.java
@@ -0,0 +1,39 @@
+package arhangel.dim.container;
+
+import org.xml.sax.SAXException;
+
+import javax.naming.NameNotFoundException;
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.IOException;
+import java.util.List;
+
+public class Messenger {
+ public static void main(String[] arg) {
+ BeanXmlReader xmlReader = new BeanXmlReader();
+ List beans;
+
+ String path = "C:\\Users\\Дмитрий\\Documents\\technotrack\\java\\messenger" +
+ "\\src\\main\\java\\arhangel\\dim\\container\\test";
+ try {
+ beans = xmlReader.parseBeans(path);
+ } catch (IOException e) {
+ System.out.println(e.getMessage());
+ return;
+ } catch (ParserConfigurationException e) {
+ System.out.println("Parsing xml-file" + e.getMessage());
+ return;
+ } catch (SAXException e) {
+ e.printStackTrace();
+ return;
+ } catch (NameNotFoundException e) {
+ System.out.println("Please add attribute (ref or val) " + e.getMessage());
+ return;
+ }
+
+ for (Bean bean : beans) {
+ System.out.println(bean.toString());
+ }
+
+
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/arhangel/dim/container/Property.java b/src/main/java/arhangel/dim/container/Property.java
index d5b2e4e..4d1a0cf 100644
--- a/src/main/java/arhangel/dim/container/Property.java
+++ b/src/main/java/arhangel/dim/container/Property.java
@@ -47,4 +47,4 @@ public String toString() {
", type=" + type +
'}';
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/arhangel/dim/container/Utils.java b/src/main/java/arhangel/dim/container/Utils.java
new file mode 100644
index 0000000..655020e
--- /dev/null
+++ b/src/main/java/arhangel/dim/container/Utils.java
@@ -0,0 +1,22 @@
+package arhangel.dim.container;
+
+import java.io.File;
+
+public class Utils {
+
+ public static String capitalize(String string) {
+ string = string.toLowerCase();
+ string = Character.toString(string.charAt(0)).toUpperCase() + string.substring(1);
+ return string;
+ }
+
+
+ public static File initFile(String pathToFile) {
+ File file = new File(pathToFile);
+ if (!file.exists()) {
+ String tryPath = System.getProperty("user.dir") + "/" + pathToFile;
+ file = new File(tryPath);
+ }
+ return file;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/arhangel/dim/container/beans/WebConnection.java b/src/main/java/arhangel/dim/container/beans/WebConnection.java
new file mode 100644
index 0000000..f2f05bf
--- /dev/null
+++ b/src/main/java/arhangel/dim/container/beans/WebConnection.java
@@ -0,0 +1,41 @@
+package arhangel.dim.container.beans;
+
+/**
+ * Created by Дмитрий on 16.05.2016.
+ */
+public class WebConnection {
+ private int port;
+ private String host;
+
+ public int getPort() {
+ return port;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public void setHost(int host) {
+ if (host == 0) {
+ this.host = "localhost";
+ }
+ }
+
+ public WebConnection() {
+ port = 9000;
+ host = "localhost";
+ }
+
+ public WebConnection(String host, int port) {
+ this.port = port;
+ this.host = host;
+ }
+}
diff --git a/src/main/java/arhangel/dim/container/test b/src/main/java/arhangel/dim/container/test
new file mode 100644
index 0000000..d678420
--- /dev/null
+++ b/src/main/java/arhangel/dim/container/test
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/arhangel/dim/core/Chat.java b/src/main/java/arhangel/dim/core/Chat.java
deleted file mode 100644
index 4363d4b..0000000
--- a/src/main/java/arhangel/dim/core/Chat.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package arhangel.dim.core;
-
-/**
- * А над этим классом надо еще поработать
- */
-public class Chat {
- private Long id;
-}
diff --git a/src/main/java/arhangel/dim/core/User.java b/src/main/java/arhangel/dim/core/User.java
deleted file mode 100644
index 0f21c0c..0000000
--- a/src/main/java/arhangel/dim/core/User.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package arhangel.dim.core;
-
-/**
- * Представление пользователя
- */
-public class User {
- private Long id;
- private String name;
-
- public Long getId() {
- return id;
- }
-
- public void setId(Long id) {
- this.id = id;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-}
diff --git a/src/main/java/arhangel/dim/core/authorization/Authorize.java b/src/main/java/arhangel/dim/core/authorization/Authorize.java
new file mode 100644
index 0000000..47ddcbe
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/authorization/Authorize.java
@@ -0,0 +1,81 @@
+package arhangel.dim.core.authorization;
+
+
+import arhangel.dim.core.message.AnswerMessage;
+import arhangel.dim.core.message.Protocol;
+import arhangel.dim.core.message.SerializationProtocol;
+import arhangel.dim.core.session.Session;
+import arhangel.dim.core.store.UserStore;
+
+import java.io.DataOutputStream;
+import java.util.List;
+
+/**
+ * Класс для авторизации и регистрации пользователей
+ */
+public class Authorize {
+
+ private UserStore userStore;
+
+ private Authorize() {}
+
+ public Authorize(UserStore userStore) {
+ this.userStore = userStore;
+ }
+
+ public synchronized void registerUser(String name, String password, Session session) throws Exception {
+ DataOutputStream writer = session.getWriter();
+ Protocol protocol = new SerializationProtocol<>();
+ String message = "";
+ AnswerMessage.Value success;
+ if (name != null && password != null) {
+ List userByName = userStore.getUserByName(name);
+ if (userByName.size() > 0) {
+ message = "Sorry, but user with this name has already registered";
+ success = AnswerMessage.Value.ERROR;
+ } else {
+ int id = userStore.addUser(new User(name, password, name));
+ session.setCurrentUserName(name);
+ session.setCurrentUserId(id);
+ message = String.format("User was successfully signed up\n" +
+ "Login: %s, Password: %s, Id: %d", name, password, id);
+ success = AnswerMessage.Value.SUCCESS;
+ }
+ } else {
+ message = "Incorrect name/password";
+ success = AnswerMessage.Value.ERROR;
+ }
+ writer.write(protocol.encode(new AnswerMessage(message, success)));
+ }
+
+ public synchronized void authorizeUser(String name, String password, Session session) throws Exception {
+ DataOutputStream writer = session.getWriter();
+ Protocol protocol = new SerializationProtocol<>();
+ String message = "";
+ AnswerMessage.Value success;
+ List userByName = userStore.getUserByName(name);
+ if (userByName.size() == 1) {
+ User user = userByName.get(0);
+ if (user.getPassword().equals(Integer.toString(password.hashCode()))) {
+ session.setCurrentUserName(name);
+ session.setCurrentUserId(user.getId());
+ message = String.format("Hello, %s! Your id = %d", name, user.getId());
+ success = AnswerMessage.Value.SUCCESS;
+ } else {
+ message = "Password is incorrect";
+ success = AnswerMessage.Value.ERROR;
+ }
+ } else {
+ message = "Sorry, but we didn't find user with this name: " + name;
+ success = AnswerMessage.Value.ERROR;
+ }
+ writer.write(protocol.encode(new AnswerMessage(message, success)));
+ }
+
+ /**
+ * Возвращает класс User по идентификатору пользователя
+ */
+ public User getUserInfo(int id) throws Exception {
+ return userStore.getUser(id);
+ }
+}
diff --git a/src/main/java/arhangel/dim/core/authorization/User.java b/src/main/java/arhangel/dim/core/authorization/User.java
new file mode 100644
index 0000000..369df2c
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/authorization/User.java
@@ -0,0 +1,48 @@
+package arhangel.dim.core.authorization;
+
+/**
+ * Класс-информация о пользователе
+ */
+public class User {
+
+ private String name;
+ private String password;
+ private String nickname;
+ private int id;
+
+ public User() {}
+
+ public User(String name, String password, String nickname) {
+ this.name = name;
+ this.password = password;
+ this.nickname = nickname;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public String getNick() {
+ return nickname;
+ }
+
+ public void setNickname(String nickname) {
+ this.nickname = nickname;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+}
diff --git a/src/main/java/arhangel/dim/core/commands/ChatCreateCommand.java b/src/main/java/arhangel/dim/core/commands/ChatCreateCommand.java
new file mode 100644
index 0000000..b813ee6
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/commands/ChatCreateCommand.java
@@ -0,0 +1,58 @@
+package arhangel.dim.core.commands;
+
+import arhangel.dim.core.store.UserStore;
+import arhangel.dim.core.message.AnswerMessage;
+import arhangel.dim.core.message.Protocol;
+import arhangel.dim.core.message.SerializationProtocol;
+import arhangel.dim.core.store.DataStore;
+import arhangel.dim.core.session.Session;
+
+import java.io.DataOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ChatCreateCommand implements Command {
+
+ /**
+ * args 0 - название команды, 1 - список участников чата через запятую
+ */
+ @Override
+ public void run(String[] args, Session session) throws Exception {
+ DataOutputStream writer = session.getWriter();
+ Protocol protocol = new SerializationProtocol<>();
+ String message = "";
+ AnswerMessage.Value success;
+ DataStore dataStore = session.getDataStore();
+ int authorId = session.getCurrentUserId();
+ if (authorId == -1) {
+ success = AnswerMessage.Value.LOGIN;
+ } else {
+ if (args.length != 2) {
+ success = AnswerMessage.Value.NUM_ARGS;
+ } else {
+ UserStore userStore = dataStore.getUserStore();
+ List participants = new ArrayList<>();
+ String[] parsedArg = args[1].split(",");
+ participants.add(authorId);
+ for (String it : parsedArg) {
+ int id = Integer.parseInt(it);
+ participants.add(id);
+ if (userStore.getUser(id) == null) {
+ message = String.format("There is no user with id %d", id);
+ success = AnswerMessage.Value.ERROR;
+ writer.write(protocol.encode(new AnswerMessage(message, success)));
+ return;
+ }
+ }
+ int result = dataStore.getChatStore().createChat(participants);
+ message = "Chat was successfully created, id: " + result;
+ success = AnswerMessage.Value.SUCCESS;
+ }
+ }
+ writer.write(protocol.encode(new AnswerMessage(message, success)));
+ }
+
+ public String toString() {
+ return "/chat_create";
+ }
+}
diff --git a/src/main/java/arhangel/dim/core/commands/ChatHistoryCommand.java b/src/main/java/arhangel/dim/core/commands/ChatHistoryCommand.java
new file mode 100644
index 0000000..9003dc3
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/commands/ChatHistoryCommand.java
@@ -0,0 +1,57 @@
+package arhangel.dim.core.commands;
+
+import arhangel.dim.core.message.AnswerMessage;
+import arhangel.dim.core.message.Chat;
+import arhangel.dim.core.message.Protocol;
+import arhangel.dim.core.message.SerializationProtocol;
+import arhangel.dim.core.message.Message;
+import arhangel.dim.core.session.Session;
+import arhangel.dim.core.store.ChatStore;
+
+import java.io.DataOutputStream;
+import java.util.Map;
+
+public class ChatHistoryCommand implements Command {
+ /**
+ * args 0 - название команды, 1 - идентификатор чата
+ */
+ @Override
+ public void run(String[] args, Session session) throws Exception {
+ DataOutputStream writer = session.getWriter();
+ Protocol protocol = new SerializationProtocol<>();
+ String message = "";
+ AnswerMessage.Value success;
+ if (session.getCurrentUserName() == null) {
+ success = AnswerMessage.Value.LOGIN;
+ writer.write(protocol.encode(new AnswerMessage(message, success)));
+ return;
+ }
+ if (args.length == 2) {
+ int chatId = Integer.parseInt(args[1]);
+ ChatStore chatStore = session.getDataStore().getChatStore();
+ Chat chat = chatStore.getChat(chatId);
+ if (chat == null) {
+ message = "Chat " + chatId + " not found";
+ success = AnswerMessage.Value.ERROR;
+ writer.write(protocol.encode(new AnswerMessage(message, success)));
+ return;
+ }
+ StringBuilder stringBuilder = new StringBuilder();
+ Map messageMap = chat.getMessageMap();
+ for (Map.Entry pair : messageMap.entrySet()) {
+ stringBuilder.append(pair.getValue().toString());
+ stringBuilder.append("\n");
+ }
+ message = stringBuilder.toString();
+ success = AnswerMessage.Value.SUCCESS;
+ } else {
+ success = AnswerMessage.Value.NUM_ARGS;
+ }
+ writer.write(protocol.encode(new AnswerMessage(message, success)));
+ }
+
+ @Override
+ public String toString() {
+ return "/chat_history";
+ }
+}
diff --git a/src/main/java/arhangel/dim/core/commands/ChatListCommand.java b/src/main/java/arhangel/dim/core/commands/ChatListCommand.java
new file mode 100644
index 0000000..fce303b
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/commands/ChatListCommand.java
@@ -0,0 +1,51 @@
+package arhangel.dim.core.commands;
+
+import arhangel.dim.core.message.AnswerMessage;
+import arhangel.dim.core.message.Chat;
+import arhangel.dim.core.message.Protocol;
+import arhangel.dim.core.message.SerializationProtocol;
+import arhangel.dim.core.store.DataStore;
+import arhangel.dim.core.session.Session;
+
+import java.io.DataOutputStream;
+import java.util.List;
+import java.util.Map;
+
+public class ChatListCommand implements Command {
+
+ @Override
+ public void run(String[] args, Session session) throws Exception {
+ DataOutputStream writer = session.getWriter();
+ Protocol protocol = new SerializationProtocol<>();
+ AnswerMessage.Value success;
+ String message = "";
+ DataStore dataStore = session.getDataStore();
+ if (session.getCurrentUserId() == -1) {
+ success = AnswerMessage.Value.LOGIN;
+ } else {
+ success = AnswerMessage.Value.SUCCESS;
+ Map result = dataStore.getChatStore().getChatList();
+ StringBuilder builder = new StringBuilder();
+ builder.append("Chat list:\n");
+ for (Map.Entry it : result.entrySet()) {
+ builder.append("Chat ");
+ builder.append(it.getKey());
+ builder.append(", users: ");
+ List participantsId = it.getValue().getParticipantIds();
+ for (Integer userIdIt : participantsId) {
+ builder.append(userIdIt);
+ builder.append(", ");
+ }
+ builder.deleteCharAt(builder.length() - 1);
+ builder.append("\n");
+ }
+ builder.deleteCharAt(builder.length() - 1);
+ message = builder.toString();
+ }
+ writer.write(protocol.encode(new AnswerMessage(message, success)));
+ }
+
+ public String toString() {
+ return "/chat_list";
+ }
+}
diff --git a/src/main/java/arhangel/dim/core/commands/Command.java b/src/main/java/arhangel/dim/core/commands/Command.java
new file mode 100644
index 0000000..e2f2e7c
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/commands/Command.java
@@ -0,0 +1,10 @@
+package arhangel.dim.core.commands;
+
+import arhangel.dim.core.session.Session;
+
+public interface Command {
+
+ void run(String[] args, Session session) throws Exception;
+
+ String toString();
+}
diff --git a/src/main/java/arhangel/dim/core/commands/HelpCommand.java b/src/main/java/arhangel/dim/core/commands/HelpCommand.java
new file mode 100644
index 0000000..d7ef314
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/commands/HelpCommand.java
@@ -0,0 +1,33 @@
+package arhangel.dim.core.commands;
+
+import arhangel.dim.core.message.AnswerMessage;
+import arhangel.dim.core.message.Protocol;
+import arhangel.dim.core.message.SerializationProtocol;
+import arhangel.dim.core.session.Session;
+
+import java.io.DataOutputStream;
+
+public class HelpCommand implements Command {
+
+ @Override
+ public void run(String[] args, Session session) throws Exception {
+ DataOutputStream writer = session.getWriter();
+ Protocol protocol = new SerializationProtocol<>();
+ String message = "List of commands:\n" +
+ " /register - sign up a user\n" +
+ " /login - sign in with these parameters\n" +
+ " /info - get the information about you\n" +
+ " /info - get the information about \'nick\'\n" +
+ " /chat_list - list of all chats\n" +
+ " /chat_create - create chat with participants in list\n" +
+ " /chat_history - show messages in \'id\' chat\n" +
+ " /text send message in 'id' chat\n" +
+ " /exit - exit the program\n" +
+ " /help - show the list of commands";
+ writer.write(protocol.encode(new AnswerMessage(message, AnswerMessage.Value.SUCCESS)));
+ }
+
+ public String toString() {
+ return "/help";
+ }
+}
diff --git a/src/main/java/arhangel/dim/core/commands/LoginCommand.java b/src/main/java/arhangel/dim/core/commands/LoginCommand.java
new file mode 100644
index 0000000..b713d80
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/commands/LoginCommand.java
@@ -0,0 +1,30 @@
+package arhangel.dim.core.commands;
+
+import arhangel.dim.core.authorization.Authorize;
+import arhangel.dim.core.message.AnswerMessage;
+import arhangel.dim.core.message.Protocol;
+import arhangel.dim.core.message.SerializationProtocol;
+import arhangel.dim.core.session.Session;
+
+import java.io.DataOutputStream;
+
+public class LoginCommand implements Command {
+ /**
+ * args 0 - название команды, 1 - логин, 2 - пароль
+ */
+ @Override
+ public void run(String[] args, Session session) throws Exception {
+ DataOutputStream writer = session.getWriter();
+ Authorize service = session.getAuthorize();
+ if (args.length == 3) {
+ service.authorizeUser(args[1], args[2], session);
+ } else {
+ Protocol protocol = new SerializationProtocol<>();
+ writer.write(protocol.encode(new AnswerMessage("", AnswerMessage.Value.NUM_ARGS)));
+ }
+ }
+
+ public String toString() {
+ return "/login";
+ }
+}
diff --git a/src/main/java/arhangel/dim/core/commands/RegisterCommand.java b/src/main/java/arhangel/dim/core/commands/RegisterCommand.java
new file mode 100644
index 0000000..4a1eb64
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/commands/RegisterCommand.java
@@ -0,0 +1,32 @@
+package arhangel.dim.core.commands;
+
+import arhangel.dim.core.authorization.Authorize;
+import arhangel.dim.core.message.AnswerMessage;
+import arhangel.dim.core.message.Protocol;
+import arhangel.dim.core.message.SerializationProtocol;
+import arhangel.dim.core.session.Session;
+
+import java.io.DataOutputStream;
+
+public class RegisterCommand implements Command {
+ /**
+ * args 0 - название команды, 1 - логин, 2 - пароль
+ */
+ @Override
+ public void run(String[] args, Session session) throws Exception {
+ Protocol protocol = new SerializationProtocol<>();
+ AnswerMessage.Value success;
+ if (args.length == 3) {
+ Authorize service = session.getAuthorize();
+ service.registerUser(args[1], args[2], session);
+ } else {
+ DataOutputStream writer = session.getWriter();
+ success = AnswerMessage.Value.NUM_ARGS;
+ writer.write(protocol.encode(new AnswerMessage("", success)));
+ }
+ }
+
+ public String toString() {
+ return "/register";
+ }
+}
diff --git a/src/main/java/arhangel/dim/core/commands/TextCommand.java b/src/main/java/arhangel/dim/core/commands/TextCommand.java
new file mode 100644
index 0000000..0452b11
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/commands/TextCommand.java
@@ -0,0 +1,75 @@
+package arhangel.dim.core.commands;
+
+import arhangel.dim.core.message.AnswerMessage;
+import arhangel.dim.core.message.Chat;
+import arhangel.dim.core.message.Protocol;
+import arhangel.dim.core.message.SerializationProtocol;
+import arhangel.dim.core.store.ChatStore;
+import arhangel.dim.core.store.DataStore;
+import arhangel.dim.core.session.Session;
+import arhangel.dim.core.session.SessionManager;
+
+import java.io.DataOutputStream;
+import java.util.List;
+
+public class TextCommand implements Command {
+ /**
+ * args 0 - название команды, 1 - идентификатор чата, 2,3,4... - сообщение
+ */
+ @Override
+ public void run(String[] args, Session session) throws Exception {
+ DataOutputStream writer = session.getWriter();
+ Protocol protocol = new SerializationProtocol<>();
+ String message = "";
+ AnswerMessage.Value success;
+ DataStore dataStore = session.getDataStore();
+ int authorId = session.getCurrentUserId();
+ String authorName = session.getCurrentUserName();
+ if (authorId == -1) {
+ success = AnswerMessage.Value.LOGIN;
+ writer.write(protocol.encode(new AnswerMessage(message, success)));
+ } else {
+ if (args.length < 3) {
+ success = AnswerMessage.Value.NUM_ARGS;
+ writer.write(protocol.encode(new AnswerMessage(message, success)));
+ return;
+ }
+ int chatId = Integer.parseInt(args[1]);
+ StringBuilder builder = new StringBuilder();
+ for (int i = 2; i < args.length; ++i) {
+ builder.append(args[i] + " ");
+ }
+ String messageFromUser = builder.toString();
+ ChatStore chatStore = dataStore.getChatStore();
+ Chat chat = chatStore.getChat(chatId);
+ if (chat == null) {
+ message = "Chat not found";
+ success = AnswerMessage.Value.ERROR;
+ writer.write(protocol.encode(new AnswerMessage(message, success)));
+ return;
+ }
+ List participants = chat.getParticipantIds();
+ if (!participants.contains(authorId)) {
+ message = "You are not allowed to write in this chat";
+ success = AnswerMessage.Value.ERROR;
+ writer.write(protocol.encode(new AnswerMessage(message, success)));
+ return;
+ }
+ chat.addMessage(authorId, authorName, messageFromUser);
+ SessionManager manager = session.getSessionManager();
+ for (Integer id : participants) {
+ success = AnswerMessage.Value.CHAT;
+ Session destinationSession = manager.getSessionById(id);
+ AnswerMessage answer = new AnswerMessage(messageFromUser, success);
+ answer.setMessage(String.format("Chat %d, from %d: %s", chatId, authorId, messageFromUser));
+ answer.setId(authorId);
+ DataOutputStream destinationWriter = destinationSession.getWriter();
+ destinationWriter.write(protocol.encode(answer));
+ }
+ }
+ }
+
+ public String toString() {
+ return "/text";
+ }
+}
diff --git a/src/main/java/arhangel/dim/core/commands/UserInfoCommand.java b/src/main/java/arhangel/dim/core/commands/UserInfoCommand.java
new file mode 100644
index 0000000..4f67566
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/commands/UserInfoCommand.java
@@ -0,0 +1,59 @@
+package arhangel.dim.core.commands;
+
+import arhangel.dim.core.authorization.Authorize;
+import arhangel.dim.core.authorization.User;
+import arhangel.dim.core.message.AnswerMessage;
+import arhangel.dim.core.message.Protocol;
+import arhangel.dim.core.message.SerializationProtocol;
+import arhangel.dim.core.session.Session;
+
+import java.io.DataOutputStream;
+
+public class UserInfoCommand implements Command {
+ /**
+ * args 0 - название команды, 1 - имя пользователя. Если аргумент 1 отсутствует, то выводятся
+ * данные о текущем пользователе
+ */
+ @Override
+ public void run(String[] args, Session session) throws Exception {
+ DataOutputStream writer = session.getWriter();
+ Protocol protocol = new SerializationProtocol<>();
+ String message = "";
+ AnswerMessage.Value success;
+ if (args.length == 1) {
+ int currentUserId = session.getCurrentUserId();
+ if (currentUserId == -1) {
+ success = AnswerMessage.Value.NUM_ARGS;
+ } else {
+ Authorize service = session.getAuthorize();
+ User user = service.getUserInfo(currentUserId);
+ if (user == null) {
+ message = "Can't find you. Don't worry.";
+ success = AnswerMessage.Value.ERROR;
+ } else {
+ message = String.format("Username: %s," +
+ " nickname: %s, Id: %d", user.getName(), user.getNick(), user.getId());
+ success = AnswerMessage.Value.SUCCESS;
+ }
+ }
+ } else if (args.length == 2) {
+ Authorize service = session.getAuthorize();
+ User user = service.getUserInfo(Integer.parseInt(args[1]));
+ if (user == null) {
+ message = "Can't find user: " + args[1];
+ success = AnswerMessage.Value.ERROR;
+ } else {
+ message = String.format("Username: %s," +
+ " nickname: %s, Id: %d", user.getName(), user.getNick(), user.getId());
+ success = AnswerMessage.Value.SUCCESS;
+ }
+ } else {
+ success = AnswerMessage.Value.NUM_ARGS;
+ }
+ writer.write(protocol.encode(new AnswerMessage(message, success)));
+ }
+
+ public String toString() {
+ return "/info";
+ }
+}
diff --git a/src/main/java/arhangel/dim/core/jdbc/DataBaseOrganizer.java b/src/main/java/arhangel/dim/core/jdbc/DataBaseOrganizer.java
new file mode 100644
index 0000000..f45d680
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/jdbc/DataBaseOrganizer.java
@@ -0,0 +1,53 @@
+package arhangel.dim.core.jdbc;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.Statement;
+
+/**
+ * Организация базы данных перед запуском(Создание таблиц).
+ */
+public class DataBaseOrganizer {
+ public static void reorganizeDataBase(String[] args) throws Exception {
+ Class.forName("org.postgresql.Driver");
+ Connection conn = DriverManager.getConnection("jdbc:postgresql://178.62.140.149:5432/Kud8",
+ "trackuser", "trackuser");
+ Statement stmt;
+ String sql;
+
+ stmt = conn.createStatement();
+ sql = "CREATE TABLE IF NOT EXISTS users " +
+ "(ID SERIAL PRIMARY KEY," +
+ " LOGIN TEXT NOT NULL," +
+ " PASSWORD TEXT NOT NULL," +
+ " NICK TEXT NOT NULL)";
+ stmt.executeUpdate(sql);
+ stmt.close();
+
+ stmt = conn.createStatement();
+ sql = "CREATE TABLE IF NOT EXISTS chats " +
+ "(ID SERIAL PRIMARY KEY," +
+ " TEMP TEXT NOT NULL)";
+ stmt.executeUpdate(sql);
+ stmt.close();
+
+ stmt = conn.createStatement();
+ sql = "CREATE TABLE IF NOT EXISTS message " +
+ "(ID SERIAL PRIMARY KEY," +
+ " AUTHOR_ID INT NOT NULL," +
+ " VALUE TEXT NOT NULL," +
+ " CHAT_ID INT NOT NULL)";
+ stmt.executeUpdate(sql);
+ stmt.close();
+
+ stmt = conn.createStatement();
+ sql = "CREATE TABLE IF NOT EXISTS userschat " +
+ "(ID SERIAL PRIMARY KEY," +
+ " USER_ID INT NOT NULL," +
+ " CHAT_ID INT NOT NULL)";
+ stmt.executeUpdate(sql);
+ stmt.close();
+
+ conn.close();
+ }
+}
diff --git a/src/main/java/arhangel/dim/core/jdbc/QueryExecutor.java b/src/main/java/arhangel/dim/core/jdbc/QueryExecutor.java
new file mode 100644
index 0000000..fdea10b
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/jdbc/QueryExecutor.java
@@ -0,0 +1,102 @@
+package arhangel.dim.core.jdbc;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Класс для отправки запросов в БД
+ */
+public class QueryExecutor {
+ /**
+ * Словарь подготовленных запросов
+ */
+ private Map preparedStatementMap;
+
+ /**
+ * Словарь подготовленных запросов, с Generated Keys
+ */
+ private Map preparedStatementMapGenKey;
+
+ public QueryExecutor() {
+ preparedStatementMap = new HashMap<>();
+ preparedStatementMapGenKey = new HashMap<>();
+ }
+
+ public void prepareStatement(Connection connection, String query) throws SQLException {
+ if (preparedStatementMap.get(query) == null) {
+ preparedStatementMap.put(query, connection.prepareStatement(query));
+ }
+ }
+
+ public void prepareStatementGeneratedKeys(Connection connection, String query) throws SQLException {
+ if (preparedStatementMapGenKey.get(query) == null) {
+ preparedStatementMapGenKey.put(query, connection.prepareStatement(query,
+ PreparedStatement.RETURN_GENERATED_KEYS));
+ }
+ }
+
+ public T execQuery(Connection connection, String query, ResultHandler handler) throws SQLException {
+ Statement stmt = connection.createStatement();
+ stmt.execute(query);
+ ResultSet result = stmt.getResultSet();
+ T value = handler.handle(result);
+ result.close();
+ stmt.close();
+
+ return value;
+ }
+
+ public T execQuery(String sql, Map args, ResultHandler handler) throws SQLException {
+ PreparedStatement pstmt = preparedStatementMap.get(sql);
+ if (pstmt == null) {
+ throw new SQLException(String.format("Statement \"%s\" wasn't prepared", sql));
+ }
+ for (Map.Entry entry : args.entrySet()) {
+ pstmt.setObject(entry.getKey(), entry.getValue());
+ }
+ ResultSet rs = pstmt.executeQuery();
+ T value = handler.handle(rs);
+ rs.close();
+ return value;
+ }
+
+ public void execUpdate(String sql, Map args) throws SQLException {
+ PreparedStatement pstmt = preparedStatementMap.get(sql);
+ if (pstmt == null) {
+ throw new SQLException(String.format("Statement \"%s\" wasn't prepared", sql));
+ }
+ for (Map.Entry entry : args.entrySet()) {
+ pstmt.setObject(entry.getKey(), entry.getValue());
+ }
+ pstmt.executeUpdate();
+ }
+
+ public T execUpdate(String sql, Map args, ResultHandler handler) throws SQLException {
+ PreparedStatement pstmt = preparedStatementMapGenKey.get(sql);
+ if (pstmt == null) {
+ throw new SQLException(String.format("Statement \"%s\" wasn't prepared", sql));
+ }
+ for (Map.Entry entry : args.entrySet()) {
+ pstmt.setObject(entry.getKey(), entry.getValue());
+ }
+ pstmt.executeUpdate();
+ ResultSet rs = pstmt.getGeneratedKeys();
+ T value = handler.handle(rs);
+ rs.close();
+ return value;
+ }
+
+ public void close() throws SQLException {
+ for (Map.Entry pair : preparedStatementMap.entrySet()) {
+ pair.getValue().close();
+ }
+ for (Map.Entry pair : preparedStatementMapGenKey.entrySet()) {
+ pair.getValue().close();
+ }
+ }
+}
diff --git a/src/main/java/arhangel/dim/lections/jdbc/ResultHandler.java b/src/main/java/arhangel/dim/core/jdbc/ResultHandler.java
similarity index 53%
rename from src/main/java/arhangel/dim/lections/jdbc/ResultHandler.java
rename to src/main/java/arhangel/dim/core/jdbc/ResultHandler.java
index 90bae13..97b2991 100644
--- a/src/main/java/arhangel/dim/lections/jdbc/ResultHandler.java
+++ b/src/main/java/arhangel/dim/core/jdbc/ResultHandler.java
@@ -1,12 +1,8 @@
-package arhangel.dim.lections.jdbc;
+package arhangel.dim.core.jdbc;
import java.sql.ResultSet;
import java.sql.SQLException;
-/**
- * Обобщенный интерфейс обработки результата
- */
-
public interface ResultHandler {
T handle(ResultSet resultSet) throws SQLException;
-}
\ No newline at end of file
+}
diff --git a/src/main/java/arhangel/dim/core/message/AnswerMessage.java b/src/main/java/arhangel/dim/core/message/AnswerMessage.java
new file mode 100644
index 0000000..655adb2
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/message/AnswerMessage.java
@@ -0,0 +1,59 @@
+package arhangel.dim.core.message;
+
+import java.io.Serializable;
+
+/**
+ * Ответ сервера на запрос клиента
+ */
+public class AnswerMessage implements Serializable {
+
+ public enum Value {
+ SUCCESS,
+ ERROR,
+ LOGIN,
+ NUM_ARGS,
+ CHAT,
+ }
+
+ private int id;
+ private String from;
+ private String message;
+ private Value result;
+
+ public AnswerMessage(String message, Value result) {
+ this.message = message;
+ this.result = result;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Value getResult() {
+ return result;
+ }
+
+ public void setResult(Value result) {
+ this.result = result;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getFrom() {
+ return from;
+ }
+
+ public void setFrom(String from) {
+ this.from = from;
+ }
+}
diff --git a/src/main/java/arhangel/dim/core/message/Chat.java b/src/main/java/arhangel/dim/core/message/Chat.java
new file mode 100644
index 0000000..ba987de
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/message/Chat.java
@@ -0,0 +1,59 @@
+package arhangel.dim.core.message;
+
+import arhangel.dim.core.store.DataBaseMessageStore;
+import arhangel.dim.core.store.MessageStore;
+
+import java.sql.Connection;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class Chat {
+
+ private Integer id;
+ private MessageStore messageStore;
+ private List participantIds;
+ private Connection connection;
+
+ public Chat(Integer id, Connection conn) {
+ this.id = id;
+ this.participantIds = new ArrayList<>();
+ this.connection = conn;
+ this.messageStore = new DataBaseMessageStore(connection, this);
+ }
+
+ public Chat(List participantIds, Integer id, Connection conn) {
+ this.id = id;
+ this.participantIds = participantIds;
+ this.connection = conn;
+ this.messageStore = new DataBaseMessageStore(conn, this);
+ }
+
+ public boolean addParticipant(int id) {
+ if (participantIds.contains(id)) {
+ return false;
+ }
+ participantIds.add(id);
+ return true;
+ }
+
+ public void addMessage(int authorId, String authorName, String message) throws Exception {
+ messageStore.addMessage(authorId, authorName, message, this);
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public List getParticipantIds() {
+ return participantIds;
+ }
+
+ public Map getMessageMap() throws Exception {
+ return messageStore.getMessagesMap();
+ }
+}
diff --git a/src/main/java/arhangel/dim/core/message/Message.java b/src/main/java/arhangel/dim/core/message/Message.java
new file mode 100644
index 0000000..b852193
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/message/Message.java
@@ -0,0 +1,65 @@
+package arhangel.dim.core.message;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+public class Message implements Serializable {
+
+ protected int id;
+ protected int authorId;
+ protected String message;
+
+ public Message() {
+
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public int getAuthorId() {
+ return authorId;
+ }
+
+ public void setAuthorId(int authorId) {
+ this.authorId = authorId;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (other == null || getClass() != other.getClass()) {
+ return false;
+ }
+ Message message = (Message) other;
+ return Objects.equals(id, message.id) &&
+ Objects.equals(authorId, message.authorId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, authorId);
+ }
+
+ @Override
+ public String toString() {
+ return "Message{" +
+ "id=" + id +
+ ", senderId=" + authorId +
+ '}';
+ }
+}
diff --git a/src/main/java/arhangel/dim/core/message/Protocol.java b/src/main/java/arhangel/dim/core/message/Protocol.java
new file mode 100644
index 0000000..077bad7
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/message/Protocol.java
@@ -0,0 +1,8 @@
+package arhangel.dim.core.message;
+
+public interface Protocol {
+
+ byte[] encode(T msg) throws Exception;
+
+ T decode(byte[] data) throws Exception;
+}
diff --git a/src/main/java/arhangel/dim/core/message/SerializationProtocol.java b/src/main/java/arhangel/dim/core/message/SerializationProtocol.java
new file mode 100644
index 0000000..08134b8
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/message/SerializationProtocol.java
@@ -0,0 +1,50 @@
+package arhangel.dim.core.message;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectInput;
+import java.nio.ByteBuffer;
+
+public class SerializationProtocol implements Protocol {
+ @Override
+ public byte[] encode(T msg) throws Exception {
+ try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutput out = new ObjectOutputStream(bos)) {
+ out.writeObject(msg);
+ byte[] objData = bos.toByteArray();
+ int size = objData.length;
+
+ ByteBuffer buf = ByteBuffer.allocate(size + 4);
+ buf.putInt(size);
+ buf.put(objData);
+ return buf.array();
+ } catch (IOException e) {
+ System.err.println("Failed to encode message " + e.toString());
+ }
+ return new byte[0];
+ }
+
+ @Override
+ public T decode(byte[] data) throws Exception {
+ ByteBuffer buf = ByteBuffer.wrap(data);
+ int size = buf.getInt();
+ if (size > data.length - 4) {
+ System.err.println("Failed to decode mesage");
+ }
+ byte[] objData = new byte[size];
+ buf.get(objData);
+ try (ByteArrayInputStream bis = new ByteArrayInputStream(objData);
+ ObjectInput in = new ObjectInputStream(bis)) {
+ return (T) in.readObject();
+ } catch (IOException e) {
+ System.err.println("Failed to decode messsage " + e.toString());
+ } catch (ClassNotFoundException e) {
+ System.err.println("Decode: no class found " + e.toString());
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/arhangel/dim/core/messages/Command.java b/src/main/java/arhangel/dim/core/messages/Command.java
deleted file mode 100644
index 533a4b6..0000000
--- a/src/main/java/arhangel/dim/core/messages/Command.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package arhangel.dim.core.messages;
-
-import arhangel.dim.core.net.Session;
-
-// TODO: на каждое сообщение завести обработчик-команду
-public interface Command {
-
- /**
- * Реализация паттерна Команда. Метод execute() вызывает соответствующую реализацию,
- * для запуска команды нужна сессия, чтобы можно было сгенерить ответ клиенту и провести валидацию
- * сессии.
- * @param session - текущая сессия
- * @param message - сообщение для обработки
- * @throws CommandException - все исключения перебрасываются как CommandException
- */
- void execute(Session session, Message message) throws CommandException;
-}
diff --git a/src/main/java/arhangel/dim/core/messages/CommandException.java b/src/main/java/arhangel/dim/core/messages/CommandException.java
deleted file mode 100644
index f6eedf1..0000000
--- a/src/main/java/arhangel/dim/core/messages/CommandException.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package arhangel.dim.core.messages;
-
-/**
- *
- */
-public class CommandException extends Exception {
- public CommandException(String msg) {
- super(msg);
- }
-
- public CommandException(Throwable ex) {
- super(ex);
- }
-}
diff --git a/src/main/java/arhangel/dim/core/messages/Message.java b/src/main/java/arhangel/dim/core/messages/Message.java
deleted file mode 100644
index 65486c8..0000000
--- a/src/main/java/arhangel/dim/core/messages/Message.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package arhangel.dim.core.messages;
-
-import java.io.Serializable;
-import java.util.Objects;
-
-/**
- * Базовый класс для всех сообщений
- */
-public abstract class Message implements Serializable {
-
- private Long id;
- private Long senderId;
- private Type type;
-
- public Long getId() {
- return id;
- }
-
- public void setId(Long id) {
- this.id = id;
- }
-
- public Long getSenderId() {
- return senderId;
- }
-
- public void setSenderId(Long senderId) {
- this.senderId = senderId;
- }
-
- public Type getType() {
- return type;
- }
-
- public void setType(Type type) {
- this.type = type;
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- }
- if (other == null || getClass() != other.getClass()) {
- return false;
- }
- Message message = (Message) other;
- return Objects.equals(id, message.id) &&
- Objects.equals(senderId, message.senderId) &&
- type == message.type;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(id, senderId, type);
- }
-
- @Override
- public String toString() {
- return "Message{" +
- "id=" + id +
- ", senderId=" + senderId +
- ", type=" + type +
- '}';
- }
-}
diff --git a/src/main/java/arhangel/dim/core/messages/TextMessage.java b/src/main/java/arhangel/dim/core/messages/TextMessage.java
deleted file mode 100644
index 59f06b5..0000000
--- a/src/main/java/arhangel/dim/core/messages/TextMessage.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package arhangel.dim.core.messages;
-
-import java.util.Objects;
-
-/**
- * Простое текстовое сообщение
- */
-public class TextMessage extends Message {
- private String text;
-
- public String getText() {
- return text;
- }
-
- public void setText(String text) {
- this.text = text;
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- }
- if (other == null || getClass() != other.getClass()) {
- return false;
- }
- if (!super.equals(other)) {
- return false;
- }
- TextMessage message = (TextMessage) other;
- return Objects.equals(text, message.text);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(super.hashCode(), text);
- }
-
- @Override
- public String toString() {
- return "TextMessage{" +
- "text='" + text + '\'' +
- '}';
- }
-}
diff --git a/src/main/java/arhangel/dim/core/messages/Type.java b/src/main/java/arhangel/dim/core/messages/Type.java
deleted file mode 100644
index 2dc0280..0000000
--- a/src/main/java/arhangel/dim/core/messages/Type.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package arhangel.dim.core.messages;
-
-/**
- * Маркер типа сообщения
- */
-public enum Type {
- MSG_LOGIN, // status
- MSG_TEXT, // status
- MSG_INFO, // MSG_INFO_RESULT
- MSG_CHAT_LIST, // MSG_CHAT_LIST_RESULT,
- MSG_CHAT_CREATE, // status
- MSG_CHAT_HIST, // MSG_CHAT_HIST_RESULT,
-
- MSG_STATUS,
- MSG_CHAT_LIST_RESULT,
- MSG_CHAT_HIST_RESULT,
- MSG_INFO_RESULT
-
-
-}
diff --git a/src/main/java/arhangel/dim/core/net/BinaryProtocol.java b/src/main/java/arhangel/dim/core/net/BinaryProtocol.java
deleted file mode 100644
index c32a6c0..0000000
--- a/src/main/java/arhangel/dim/core/net/BinaryProtocol.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package arhangel.dim.core.net;
-
-import arhangel.dim.core.messages.Message;
-
-/**
- * TODO: реализовать здесь свой протокол
- */
-public class BinaryProtocol implements Protocol {
-
- @Override
- public Message decode(byte[] bytes) throws ProtocolException {
- return null;
- }
-
- @Override
- public byte[] encode(Message msg) throws ProtocolException {
- return new byte[0];
- }
-}
diff --git a/src/main/java/arhangel/dim/core/net/ConnectionHandler.java b/src/main/java/arhangel/dim/core/net/ConnectionHandler.java
deleted file mode 100644
index c5df653..0000000
--- a/src/main/java/arhangel/dim/core/net/ConnectionHandler.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package arhangel.dim.core.net;
-
-import java.io.IOException;
-
-import arhangel.dim.core.messages.Message;
-
-/**
- * Описывает поведение слушателя сокета
- *
- */
-public interface ConnectionHandler {
-
- /**
- * Отправить сообщение.
- * Требуется обработать 2 типа ошибок
- * @throws ProtocolException - ошибка протокола (не получилось кодировать/декодировать)
- * @throws IOException - ошибка чтения/записи данных в сеть
- */
- void send(Message msg) throws ProtocolException, IOException;
-
- /**
- * Реакция на сообщение, пришедшее из сети
- */
- void onMessage(Message msg);
-
- /**
- * Молча (без проброса ошибок) закрываем соединение и освобождаем ресурсы
- */
- void close();
-
-}
diff --git a/src/main/java/arhangel/dim/core/net/Protocol.java b/src/main/java/arhangel/dim/core/net/Protocol.java
deleted file mode 100644
index e858333..0000000
--- a/src/main/java/arhangel/dim/core/net/Protocol.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package arhangel.dim.core.net;
-
-import arhangel.dim.core.messages.Message;
-
-/**
- *
- */
-public interface Protocol {
-
- Message decode(byte[] bytes) throws ProtocolException;
-
- byte[] encode(Message msg) throws ProtocolException;
-
-}
diff --git a/src/main/java/arhangel/dim/core/net/ProtocolException.java b/src/main/java/arhangel/dim/core/net/ProtocolException.java
deleted file mode 100644
index e121590..0000000
--- a/src/main/java/arhangel/dim/core/net/ProtocolException.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package arhangel.dim.core.net;
-
-/**
- *
- */
-public class ProtocolException extends Exception {
- public ProtocolException(String msg) {
- super(msg);
- }
-
- public ProtocolException(Throwable ex) {
- super(ex);
- }
-}
diff --git a/src/main/java/arhangel/dim/core/net/Session.java b/src/main/java/arhangel/dim/core/net/Session.java
deleted file mode 100644
index f9a161f..0000000
--- a/src/main/java/arhangel/dim/core/net/Session.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package arhangel.dim.core.net;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.Socket;
-
-import arhangel.dim.core.User;
-import arhangel.dim.core.messages.Message;
-
-/**
- * Здесь храним всю информацию, связанную с отдельным клиентом.
- * - объект User - описание пользователя
- * - сокеты на чтение/запись данных в канал пользователя
- */
-public class Session implements ConnectionHandler {
-
- /**
- * Пользователь сессии, пока не прошел логин, user == null
- * После логина устанавливается реальный пользователь
- */
- private User user;
-
- // сокет на клиента
- private Socket socket;
-
- /**
- * С каждым сокетом связано 2 канала in/out
- */
- private InputStream in;
- private OutputStream out;
-
- @Override
- public void send(Message msg) throws ProtocolException, IOException {
- // TODO: Отправить клиенту сообщение
- }
-
- @Override
- public void onMessage(Message msg) {
- // TODO: Пришло некое сообщение от клиента, его нужно обработать
- }
-
- @Override
- public void close() {
- // TODO: закрыть in/out каналы и сокет. Освободить другие ресурсы, если необходимо
- }
-}
diff --git a/src/main/java/arhangel/dim/core/net/StringProtocol.java b/src/main/java/arhangel/dim/core/net/StringProtocol.java
deleted file mode 100644
index d4cd40a..0000000
--- a/src/main/java/arhangel/dim/core/net/StringProtocol.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package arhangel.dim.core.net;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import arhangel.dim.core.messages.Message;
-import arhangel.dim.core.messages.TextMessage;
-import arhangel.dim.core.messages.Type;
-
-/**
- * Простейший протокол передачи данных
- */
-public class StringProtocol implements Protocol {
-
- static Logger log = LoggerFactory.getLogger(StringProtocol.class);
-
- public static final String DELIMITER = ";";
-
- @Override
- public Message decode(byte[] bytes) throws ProtocolException {
- String str = new String(bytes);
- log.info("decoded: {}", str);
- String[] tokens = str.split(DELIMITER);
- Type type = Type.valueOf(tokens[0]);
- switch (type) {
- case MSG_TEXT:
- TextMessage textMsg = new TextMessage();
- textMsg.setSenderId(parseLong(tokens[1]));
- textMsg.setText(tokens[2]);
- textMsg.setType(type);
- return textMsg;
- default:
- throw new ProtocolException("Invalid type: " + type);
- }
- }
-
- @Override
- public byte[] encode(Message msg) throws ProtocolException {
- StringBuilder builder = new StringBuilder();
- Type type = msg.getType();
- builder.append(type).append(DELIMITER);
- switch (type) {
- case MSG_TEXT:
- TextMessage sendMessage = (TextMessage) msg;
- builder.append(String.valueOf(sendMessage.getSenderId())).append(DELIMITER);
- builder.append(sendMessage.getText()).append(DELIMITER);
- break;
- default:
- throw new ProtocolException("Invalid type: " + type);
-
-
- }
- log.info("encoded: {}", builder.toString());
- return builder.toString().getBytes();
- }
-
- private Long parseLong(String str) {
- try {
- return Long.parseLong(str);
- } catch (Exception e) {
- // who care
- }
- return null;
- }
-}
diff --git a/src/main/java/arhangel/dim/core/session/Session.java b/src/main/java/arhangel/dim/core/session/Session.java
new file mode 100644
index 0000000..7a457b6
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/session/Session.java
@@ -0,0 +1,75 @@
+package arhangel.dim.core.session;
+
+import arhangel.dim.core.authorization.Authorize;
+import arhangel.dim.core.store.DataStore;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+
+/**
+ * Хранение данных о текущей сессии с клиентом
+ */
+public class Session {
+ /**
+ * Потоки для общения с клиентом
+ */
+ private DataInputStream reader;
+ private DataOutputStream writer;
+
+ /**
+ * Сервис авторизации и регистрации клиентов
+ */
+ private Authorize authorize;
+
+ private DataStore dataStore;
+ private String currentUserName;
+ private int currentUserId;
+
+ private SessionManager sessionManager;
+
+ public Session(DataInputStream reader, DataOutputStream writer,
+ Authorize authService, DataStore dataStore, SessionManager manager) {
+ this.reader = reader;
+ this.writer = writer;
+ this.authorize = authService;
+ this.dataStore = dataStore;
+ this.sessionManager = manager;
+ this.currentUserId = -1;
+ }
+
+ public DataInputStream getReader() {
+ return reader;
+ }
+
+ public DataOutputStream getWriter() {
+ return writer;
+ }
+
+ public Authorize getAuthorize() {
+ return authorize;
+ }
+
+ public String getCurrentUserName() {
+ return currentUserName;
+ }
+
+ public void setCurrentUserName(String currentUserName) {
+ this.currentUserName = currentUserName;
+ }
+
+ public DataStore getDataStore() {
+ return dataStore;
+ }
+
+ public SessionManager getSessionManager() {
+ return sessionManager;
+ }
+
+ public int getCurrentUserId() {
+ return currentUserId;
+ }
+
+ public void setCurrentUserId(int currentUserId) {
+ this.currentUserId = currentUserId;
+ }
+}
diff --git a/src/main/java/arhangel/dim/core/session/SessionManager.java b/src/main/java/arhangel/dim/core/session/SessionManager.java
new file mode 100644
index 0000000..0d3c850
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/session/SessionManager.java
@@ -0,0 +1,36 @@
+package arhangel.dim.core.session;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Хранение всех активных сессий
+ */
+public class SessionManager {
+ private Set sessions;
+
+ public SessionManager() {
+ sessions = new HashSet<>();
+ }
+
+ public Set getSessions() {
+ return sessions;
+ }
+
+ public void setSessions(Set sessions) {
+ this.sessions = sessions;
+ }
+
+ public synchronized void addSession(Session session) {
+ sessions.add(session);
+ }
+
+ public Session getSessionById(int id) {
+ for (Session it: sessions) {
+ if (it.getCurrentUserId() == id) {
+ return it;
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/arhangel/dim/core/store/ChatStore.java b/src/main/java/arhangel/dim/core/store/ChatStore.java
new file mode 100644
index 0000000..0530c33
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/store/ChatStore.java
@@ -0,0 +1,18 @@
+package arhangel.dim.core.store;
+
+import arhangel.dim.core.message.Chat;
+
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Map;
+
+public interface ChatStore {
+
+ int createChat(List participants) throws Exception;
+
+ Map getChatList() throws Exception;
+
+ Chat getChat(Integer id) throws Exception;
+
+ void close() throws SQLException;
+}
diff --git a/src/main/java/arhangel/dim/core/store/DataBaseChatStore.java b/src/main/java/arhangel/dim/core/store/DataBaseChatStore.java
new file mode 100644
index 0000000..52b951c
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/store/DataBaseChatStore.java
@@ -0,0 +1,91 @@
+package arhangel.dim.core.store;
+
+import arhangel.dim.core.jdbc.QueryExecutor;
+import arhangel.dim.core.message.Chat;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Реализация хранилища чатов в БД PostegreSql
+ */
+
+public class DataBaseChatStore implements ChatStore {
+ private Connection connection;
+ private QueryExecutor executor;
+
+ public DataBaseChatStore(Connection conn) {
+ this.connection = conn;
+ this.executor = new QueryExecutor();
+ }
+
+ @Override
+ public synchronized int createChat(List participants) throws Exception {
+ int chatId = -1;
+ String sql = "INSERT INTO chats (temp) VALUES (?)";
+ Map queryArgs = new HashMap<>();
+ queryArgs.put(1, "temp");
+ executor.prepareStatementGeneratedKeys(connection, sql);
+ chatId = executor.execUpdate(sql, queryArgs, (resSet) -> {
+ if (resSet.next()) {
+ return resSet.getInt(1);
+ }
+ return -1;
+ });
+ sql = "INSERT INTO userschat (user_id, chat_id) VALUES (?, ?)";
+ executor.prepareStatement(connection, sql);
+ for (Integer userId : participants) {
+ queryArgs.clear();
+ queryArgs.put(1, userId);
+ queryArgs.put(2, chatId);
+ executor.execUpdate(sql, queryArgs);
+ }
+ return chatId;
+ }
+
+ @Override
+ public Map getChatList() throws Exception {
+ String sql = "SELECT * FROM userschat";
+ return executor.execQuery(connection, sql, (resSet) -> {
+ Map result = new HashMap<>();
+ while (resSet.next()) {
+ int chatId = resSet.getInt("chat_id");
+ int userId = resSet.getInt("user_id");
+ Chat chat = result.get(chatId);
+ if (chat == null) {
+ chat = new Chat(chatId, connection);
+ chat.addParticipant(userId);
+ result.put(chatId, chat);
+ } else {
+ chat.addParticipant(userId);
+ }
+ }
+ return result;
+ });
+ }
+
+ @Override
+ public Chat getChat(Integer id) throws Exception {
+ Chat result = new Chat(id, connection);
+ String sql = "SELECT * FROM userschat WHERE chat_id = ?";
+ Map queryArgs = new HashMap<>();
+ queryArgs.put(1, id);
+ executor.prepareStatement(connection, sql);
+ executor.execQuery(sql, queryArgs, (resSet) -> {
+ while (resSet.next()) {
+ int userId = resSet.getInt("user_id");
+ result.addParticipant(userId);
+ }
+ return null;
+ });
+ return result;
+ }
+
+ @Override
+ public void close() throws SQLException {
+ executor.close();
+ }
+}
diff --git a/src/main/java/arhangel/dim/core/store/DataBaseMessageStore.java b/src/main/java/arhangel/dim/core/store/DataBaseMessageStore.java
new file mode 100644
index 0000000..10e99be
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/store/DataBaseMessageStore.java
@@ -0,0 +1,71 @@
+package arhangel.dim.core.store;
+
+import arhangel.dim.core.jdbc.QueryExecutor;
+import arhangel.dim.core.message.Chat;
+import arhangel.dim.core.message.Message;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Реализация хранилища сообщений на БД PostegreSQL
+ */
+public class DataBaseMessageStore implements MessageStore {
+ private Connection connection;
+ private int chatId;
+ private QueryExecutor executor;
+
+ public DataBaseMessageStore(Connection conn, Chat chat) {
+ this.connection = conn;
+ this.chatId = chat.getId();
+ this.executor = new QueryExecutor();
+ }
+
+ @Override
+ public synchronized void addMessage(int authorId, String authorName, String value, Chat chat) throws Exception {
+ try {
+ if (value.contains("\'")) {
+ value = value.replace('\'', ' ');
+ }
+ String sql = "INSERT INTO message (author_id, value, chat_id) VALUES (? ,? ,?)";
+ Map queryArgs = new HashMap<>();
+ queryArgs.put(1, authorId);
+ queryArgs.put(2, value);
+ queryArgs.put(3, chat.getId());
+ executor.prepareStatement(connection, sql);
+ executor.execUpdate(sql, queryArgs);
+ } catch (Exception e) {
+ System.err.println("MessageStore: failed to write data " + e.getMessage());
+ }
+ }
+
+ @Override
+ public synchronized Map getMessagesMap() throws Exception {
+ Map messageMap = new HashMap<>();
+ String sql = "SELECT * FROM message WHERE chat_id = ? LIMIT 10000";
+ Map queryArgs = new HashMap<>();
+ queryArgs.put(1, chatId);
+ executor.prepareStatement(connection, sql);
+ executor.execQuery(sql, queryArgs, (r) -> {
+ while (r.next()) {
+ int authorId = r.getInt("author_id");
+ String value = r.getString("value");
+ int messageId = r.getInt("id");
+ Message message = new Message();
+ message.setAuthorId(authorId);
+ message.setMessage(value);
+ message.setId(messageId);
+ messageMap.put(messageId, message);
+ }
+ return null;
+ });
+ return messageMap;
+ }
+
+ @Override
+ public void close() throws SQLException {
+ executor.close();
+ }
+}
diff --git a/src/main/java/arhangel/dim/core/store/DataBaseUserStore.java b/src/main/java/arhangel/dim/core/store/DataBaseUserStore.java
new file mode 100644
index 0000000..5bff869
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/store/DataBaseUserStore.java
@@ -0,0 +1,106 @@
+package arhangel.dim.core.store;
+
+import arhangel.dim.core.authorization.User;
+import arhangel.dim.core.jdbc.QueryExecutor;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Хранилище пользователей, реализованное на базе данных PostegreSql.
+ */
+public class DataBaseUserStore implements UserStore {
+ /**
+ * Соединение с БД
+ */
+ private Connection connection;
+
+ /**
+ * Исполнитель SQL-запросов
+ */
+ private QueryExecutor executor;
+
+ public DataBaseUserStore(Connection conn) {
+ this.connection = conn;
+ this.executor = new QueryExecutor();
+ }
+
+ @Override
+ public synchronized List getUserByName(String name) throws Exception {
+ if (name == null) {
+ return null;
+ }
+ Map queryArgs = new HashMap<>();
+ queryArgs.put(1, name);
+ String sql = "SELECT * FROM USERS where LOGIN = ?";
+ executor.prepareStatement(connection, sql);
+ return executor.execQuery(sql, queryArgs, (resSet) -> {
+ List data = new ArrayList<>();
+ while (resSet.next()) {
+ User user = new User(resSet.getString("login"),
+ resSet.getString("password"),
+ resSet.getString("nick"));
+
+ int id = resSet.getInt("id");
+ user.setId(id);
+ data.add(user);
+ }
+ return data;
+ });
+ }
+
+ @Override
+ public synchronized User getUser(int id) throws Exception {
+ if (id < 0) {
+ return null;
+ }
+ Map queryArgs = new HashMap<>();
+ queryArgs.put(1, id);
+ String sql = "SELECT * FROM USERS where ID = ?";
+ executor.prepareStatement(connection, sql);
+ return executor.execQuery(sql, queryArgs, (resSet) -> {
+ User result = new User();
+ while (resSet.next()) {
+ result = new User(resSet.getString("login"), resSet.getString("password"), resSet.getString("nick"));
+ result.setId(id);
+ }
+ return result;
+ });
+ }
+
+ @Override
+ public synchronized int addUser(User user) throws Exception {
+ if (user == null) {
+ System.out.println("Can't add user");
+ return -1;
+ }
+ int result = -1;
+ try {
+ Map queryArgs = new HashMap<>();
+ queryArgs.put(1, user.getName());
+ queryArgs.put(2, Integer.toString(user.getPassword().hashCode()));
+ queryArgs.put(3, user.getName());
+ String sql = "INSERT INTO USERS (LOGIN, PASSWORD, NICK) VALUES (?, ?, ? )";
+ executor.prepareStatementGeneratedKeys(connection, sql);
+ result = executor.execUpdate(sql, queryArgs, (resSet) -> {
+ if (resSet.next()) {
+ return resSet.getInt(1);
+ }
+ return -1;
+ });
+ } catch (Exception e) {
+ System.err.println("UserStore: failed to write data " + e.getMessage());
+ throw e;
+ }
+ return result;
+ }
+
+ @Override
+ public void close() throws SQLException {
+ executor.close();
+ }
+}
diff --git a/src/main/java/arhangel/dim/core/store/DataStore.java b/src/main/java/arhangel/dim/core/store/DataStore.java
new file mode 100644
index 0000000..e338272
--- /dev/null
+++ b/src/main/java/arhangel/dim/core/store/DataStore.java
@@ -0,0 +1,61 @@
+package arhangel.dim.core.store;
+
+
+import arhangel.dim.core.commands.Command;
+import arhangel.dim.core.commands.LoginCommand;
+import arhangel.dim.core.commands.RegisterCommand;
+import arhangel.dim.core.commands.UserInfoCommand;
+import arhangel.dim.core.commands.TextCommand;
+import arhangel.dim.core.commands.ChatCreateCommand;
+import arhangel.dim.core.commands.ChatHistoryCommand;
+import arhangel.dim.core.commands.ChatListCommand;
+import arhangel.dim.core.commands.HelpCommand;
+
+import java.sql.Connection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Объединение всех хранилищ
+ */
+public class DataStore {
+ private UserStore userStore;
+ private Map commandsStore;
+ private ChatStore chatStore;
+ private Connection connection;
+
+ public DataStore(UserStore fileUserStore, ChatStore chatStore, Connection conn) {
+ this.userStore = fileUserStore;
+ this.chatStore = chatStore;
+ this.connection = conn;
+ commandsStore = new HashMap<>();
+ commandsStore.put("/register", new RegisterCommand());
+ commandsStore.put("/login", new LoginCommand());
+ commandsStore.put("/info", new UserInfoCommand());
+ commandsStore.put("/chat_list", new ChatListCommand());
+ commandsStore.put("/chat_create", new ChatCreateCommand());
+ commandsStore.put("/chat_history", new ChatHistoryCommand());
+ commandsStore.put("/text", new TextCommand());
+ commandsStore.put("/help", new HelpCommand());
+
+ }
+
+ public UserStore getUserStore() {
+ return userStore;
+ }
+
+ public ChatStore getChatStore() {
+ return chatStore;
+ }
+
+ public Map getCommandsStore() {
+ return commandsStore;
+ }
+
+ public Connection getConnection() {
+ return connection;
+ }
+
+ public void close() throws Exception {
+ }
+}
diff --git a/src/main/java/arhangel/dim/core/store/MessageStore.java b/src/main/java/arhangel/dim/core/store/MessageStore.java
index e16bed8..807e27b 100644
--- a/src/main/java/arhangel/dim/core/store/MessageStore.java
+++ b/src/main/java/arhangel/dim/core/store/MessageStore.java
@@ -1,44 +1,19 @@
package arhangel.dim.core.store;
-import java.util.List;
+import java.sql.SQLException;
+import java.util.Map;
-import arhangel.dim.core.Chat;
-import arhangel.dim.core.messages.Message;
+import arhangel.dim.core.message.Chat;
+import arhangel.dim.core.message.Message;
/**
* Хранилище информации о сообщениях
*/
public interface MessageStore {
- /**
- * получаем список ид пользователей заданного чата
- */
- List getChatsByUserId(Long userId);
-
- /**
- * получить информацию о чате
- */
- Chat getChatById(Long chatId);
-
- /**
- * Список сообщений из чата
- */
- List getMessagesFromChat(Long chatId);
-
- /**
- * Получить информацию о сообщении
- */
- Message getMessageById(Long messageId);
-
- /**
- * Добавить сообщение в чат
- */
- void addMessage(Long chatId, Message message);
-
- /**
- * Добавить пользователя к чату
- */
- void addUserToChat(Long userId, Long chatId);
+ void addMessage(int authorId, String from, String message, Chat chat) throws Exception;
+ Map getMessagesMap() throws Exception;
+ void close() throws SQLException;
}
diff --git a/src/main/java/arhangel/dim/core/store/UserStore.java b/src/main/java/arhangel/dim/core/store/UserStore.java
index d13ce6f..524f562 100644
--- a/src/main/java/arhangel/dim/core/store/UserStore.java
+++ b/src/main/java/arhangel/dim/core/store/UserStore.java
@@ -1,34 +1,20 @@
package arhangel.dim.core.store;
-import arhangel.dim.core.User;
+import arhangel.dim.core.authorization.User;
+
+import java.sql.SQLException;
+import java.util.List;
+
/**
- * Хранилище информации о пользователе
+ * Хранилище пользователей
*/
public interface UserStore {
+ User getUser(int id) throws Exception;
- /**
- * Добавить пользователя в хранилище
- * Вернуть его же
- */
- User addUser(User user);
-
- /**
- * Обновить информацию о пользователе
- */
- User updateUser(User user);
+ List getUserByName(String name) throws Exception;
- /**
- *
- * Получить пользователя по логину/паролю
- * return null if user not found
- */
- User getUser(String login, String pass);
+ int addUser(User user) throws Exception;
- /**
- *
- * Получить пользователя по id, например запрос информации/профиля
- * return null if user not found
- */
- User getUserById(Long id);
+ void close() throws SQLException;
}
diff --git a/src/main/java/arhangel/dim/lections/classez/IntWrapper.java b/src/main/java/arhangel/dim/lections/classez/IntWrapper.java
deleted file mode 100644
index 7359449..0000000
--- a/src/main/java/arhangel/dim/lections/classez/IntWrapper.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package arhangel.dim.lections.classez;
-
-/**
- * Created by Rustam on 29.03.2016.
- */
-public class IntWrapper {
-
- Monad operation;
- Monad num;
-
- public IntWrapper setOperation(Monad operation) {
- this.operation = operation;
- return this;
- }
-
- public IntWrapper setNum(Monad num) {
- this.num = num;
- return this;
- }
-
- public int calculate(int num2) {
- int result = 0;
- operation.apply("asd");
- num.apply(12);
-// switch (operation) {
-// case "+": result = num + num2; break;
-// case "-": result = num - num2; break;
-// }
- return result;
- }
-
- interface Monad {
- T apply(T arg);
- }
-}
diff --git a/src/main/java/arhangel/dim/lections/classez/Main.java b/src/main/java/arhangel/dim/lections/classez/Main.java
deleted file mode 100644
index f5ed91f..0000000
--- a/src/main/java/arhangel/dim/lections/classez/Main.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package arhangel.dim.lections.classez;
-
-/**
- * Created by r.kildiev on 29.03.2016.
- */
-
-//Lecture Slides https://drive.google.com/open?id=0Bz3AMLjdKktjdDl6MXhQTFBIU2M
-public class Main {
- public static void main(String[] args) {
- Outer outer = new Outer();
- outer.anonymous();
-// Outer.Inner innerClass = outer.inner;
-// System.out.println(innerClass.localInt);
-// Outer.Inner inner2 = new Outer.Inner();
-
- IntWrapper intWrapper = new IntWrapper();
- intWrapper.setOperation(new IntWrapper.Monad() {
- @Override
- public String apply(String arg) {
- System.out.println("apply String");
- return "++".substring(1);
- }
- })
- .setNum(new IntWrapper.Monad() {
- @Override
- public Integer apply(Integer arg) {
- System.out.println("apply Integer");
- return arg + 1;
- }
- })
- .calculate(3)
- ;
- }
-}
diff --git a/src/main/java/arhangel/dim/lections/classez/Outer.java b/src/main/java/arhangel/dim/lections/classez/Outer.java
deleted file mode 100644
index 45fa04f..0000000
--- a/src/main/java/arhangel/dim/lections/classez/Outer.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package arhangel.dim.lections.classez;
-
-/**
- * Created by r.kildiev on 29.03.2016.
- */
-class Outer {
- Inner inner = new Inner();
-
- void anonymous() {
-
- HelloWorld greeting = /*class $1 implements*/new HelloWorld() {
- public String greet() {
- System.out.println("Hello World");
- return null;
- }
- };
- String result = greeting.greet().substring(3);
- }
-
- interface HelloWorld {
- public String greet();
- }
-
- class Inner {
- int innerField = 0;
- int localInt = 1;
-
- String local = new String();
-
- public Inner() {
-
- }
-
- void localMethod() {
- /*private*/
- class Local {
- int outerLocalInt;
- int localInt = 2;
-
- // static String field = "";
- public Local() {
- }
- }
-// int localInt = local.localInt;
- //blah blah code
- }
- }
-
-}
diff --git a/src/main/java/arhangel/dim/lections/collections/BoundGenerics.java b/src/main/java/arhangel/dim/lections/collections/BoundGenerics.java
deleted file mode 100644
index 2f982b0..0000000
--- a/src/main/java/arhangel/dim/lections/collections/BoundGenerics.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package arhangel.dim.lections.collections;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- *
- */
-public class BoundGenerics {
-
- static class Animal {
- void feed() {
- System.out.println("Animal feed()");
- }
- }
-
- static class Pet extends Animal {
- void call() {
- System.out.println("Pet call()");
- }
- }
-
- static class Cat extends Pet {
- void mew() {
- System.out.println("Cat mew()");
- }
- }
-
- static class Dog extends Pet {
- void bark() {
- System.out.println("Dog bark()");
- }
- }
-
-
- static void fillPets(List pets) {
- pets.add(new Dog());
- pets.add(new Cat());
- }
-
- static void copy(List super T> dest, List extends T> src) {
-
- for (T e : src) {
- dest.add(e);
- }
-
- // src.stream().forEach(dest::add);
- }
-
- public static void main(String[] args) {
- List cats = new ArrayList<>();
- cats.add(new Cat());
- cats.add(new Cat());
-
-
- List extends Pet> pets = cats;
-
-
- List dogs = new ArrayList<>();
- dogs.add(new Dog());
- dogs.add(new Dog());
-
- callPets(cats); // Incompatible types (compile time)
-// callPets(dogs);
-
-
- List animals = new ArrayList<>();
- // Incompatible types
-// fillPets(animals);
-
- }
-
-// static void callPets(List list) {
-// // Позовем домашних питомцев
-// for (Pet pet : list) {
-// pet.call();
-// }
-// }
-
- // Коллекция pets - поставщик данных (producer)
-// static void callPets(List pets) {
-// for (T item : pets) {
-// item.call();
-// }
-//
-// //pets.stream().forEach(Pet::call);
-// }
-
-
- static void callPets(List extends Pet> pets) {
- pets.stream().forEach(Pet::call);
- }
-
-
- // Коллекция pets - потребитель данных (consumer)
-// static void fillPets(List super Pet> pets) {
-// pets.add(new Dog());
-// pets.add(new Cat());
-// }
-
-
-}
diff --git a/src/main/java/arhangel/dim/lections/collections/Box.java b/src/main/java/arhangel/dim/lections/collections/Box.java
deleted file mode 100644
index 468d37c..0000000
--- a/src/main/java/arhangel/dim/lections/collections/Box.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package arhangel.dim.lections.collections;
-
-/**
- *
- */
-public class Box {
- private T item;
-
- public Box(T item) {
- this.item = item;
- }
-
- public T getItem() {
- return item;
- }
-
- public void setItem(T item) {
- this.item = item;
- // Object - nothing more
- }
-
- @Override
- public String toString() {
- return "Box{" +
- "item=" + item +
- '}';
- }
-}
diff --git a/src/main/java/arhangel/dim/lections/collections/Demo.java b/src/main/java/arhangel/dim/lections/collections/Demo.java
deleted file mode 100644
index d862eae..0000000
--- a/src/main/java/arhangel/dim/lections/collections/Demo.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package arhangel.dim.lections.collections;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.function.Consumer;
-import java.util.function.Predicate;
-
-/**
- * 7
- */
-public class Demo {
-
- // SAM - Single Abstract Method
- static class MyPredicate implements Predicate {
- @Override
- public boolean test(Integer integer) {
- return integer % 2 != 0;
- }
- }
-
- static class MyConsumer implements Consumer {
- @Override
- public void accept(T item) {
- System.out.println("# " + item);
- }
- }
-
- public static void main(String[] args) {
- List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
-
- // Filter with predicate
- final int skip = 3;
- // skip = 4;
- numbers.stream().filter(new MyPredicate()).forEach(new MyConsumer<>());
-
- numbers
- .stream()
- .filter((val) -> val != skip)
- .forEach(System.out::println);
-
-
- // Map
-
- int sum = numbers.stream()
- .map((val) -> val * val)
- .reduce(0, (val1, val2) -> val1 + val2);
- System.out.println("sum: " + sum);
-
-
- List myList =
- Arrays.asList("a1", "a2", "b1", "c2", "c1");
-
- myList.stream()
- .filter(s -> s.startsWith("c"))
- .map(String::toUpperCase)
- .sorted()
- .forEach(System.out::println);
-
- }
-}
diff --git a/src/main/java/arhangel/dim/lections/collections/FunctionalProgramming.java b/src/main/java/arhangel/dim/lections/collections/FunctionalProgramming.java
deleted file mode 100644
index 53a84da..0000000
--- a/src/main/java/arhangel/dim/lections/collections/FunctionalProgramming.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package arhangel.dim.lections.collections;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-
-public class FunctionalProgramming {
-
- // Принимает одно значение, возвращает одно значение
- interface Function {
- R apply(T val);
- }
-
- // Принимает элемент и проверяет его на условие
- interface Predicate {
- boolean test(T val);
- }
-
- // Принимает 2 аргумента, проводит опреацию и возвращает результат
- interface BiFunction {
- R apply(U val1, V val2);
- }
-
- // 2 аргумента одного типа
- interface BiOperator extends BiFunction {
- T apply(T val1, T val2);
- }
-
- static class Square implements Function {
- public Integer apply(Integer val) {
- return val * val;
- }
- }
-
- /*
- Применить к каждому элементу коллекции заданную операцию
- */
- static List map(Collection collection, Function functor) {
- return Collections.emptyList();
- }
-
- /*
- Проверить элементы коллекции на заданное условие.
- Вернуть коллекцию элементов, прошедших фильтр
- */
- static List filter(List list, Predicate predicate) {
- return Collections.emptyList();
- }
-
- /*
- Последовательно применить операцию ко всем элементам коллекции
- Вернуть одно значение
- */
- static T reduce(List list, T init, BiOperator op) {
- return null;
- }
-
- public static void main(String[] args) {
- List numbers = Arrays.asList(1, 2, 3, 4);
-
- // Returned 1, 4, 9, 16
- System.out.println("map [^2]: " + numbers + " -> " + map(numbers, new Square()));
-
- System.out.println("filter [%3]: " + numbers + " -> " + filter(numbers, new Predicate() {
- @Override
- public boolean test(Integer val) {
- return val % 3 != 0;
- }
- }));
-
- }
-}
diff --git a/src/main/java/arhangel/dim/lections/collections/Stack.java b/src/main/java/arhangel/dim/lections/collections/Stack.java
deleted file mode 100644
index a04f604..0000000
--- a/src/main/java/arhangel/dim/lections/collections/Stack.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package arhangel.dim.lections.collections;
-
-import java.util.Collection;
-
-/**
- *
- */
-public interface Stack extends Iterable {
-
- void push(E element) throws StackException;
-
- E pop() throws StackException;
-
- E peek();
-
- int getSize();
-
- boolean isEmpty();
-
- boolean isFull();
-
- // A little bit wrong =( Could you fix it?
- void pushAll(Collection src) throws StackException;
-
- void popAll(Collection dst) throws StackException;
-}
diff --git a/src/main/java/arhangel/dim/lections/collections/StackException.java b/src/main/java/arhangel/dim/lections/collections/StackException.java
deleted file mode 100644
index afdd057..0000000
--- a/src/main/java/arhangel/dim/lections/collections/StackException.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package arhangel.dim.lections.collections;
-
-/**
- *
- */
-public class StackException extends Exception {
- public StackException(String msg) {
- super(msg);
- }
-}
diff --git a/src/main/java/arhangel/dim/lections/exception/ExceptionDemo.java b/src/main/java/arhangel/dim/lections/exception/ExceptionDemo.java
deleted file mode 100644
index 35295fa..0000000
--- a/src/main/java/arhangel/dim/lections/exception/ExceptionDemo.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package arhangel.dim.lections.exception;
-
-
-import java.io.IOException;
-import java.sql.Connection;
-
-/**
- *
- */
-public class ExceptionDemo {
-
- public static void convertString(String str) {
- if (str == null) {
- throw new IllegalArgumentException("Arg str must be non-null");
- }
- }
-
- public static void m1() throws Exception {
- throw new ArithmeticException("Amth");
- }
-
- public static void m2() throws Exception {
- try {
- m1();
- } catch (Exception e) {
- throw new Exception(e);
- }
- }
-
- public static void main(String[] args) throws Exception {
-
- try {
- m2();
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- }
-
- //convertString(null);
-
-// System.out.println("str == null -> " + getSize(null));
-// System.out.println("str != null -> " + getSize("test"));
-
- //exceptionLost();
-
- }
-
- public static int getSize(String str) {
- Connection conn = null;
- try {
- return str.length();
- } catch (Exception e) {
- System.out.println("in catch block");
- //System.exit(0);
- return -1;
- } finally {
- if (conn != null) {
- try {
- conn.close();
- } catch (Exception e) {
- // do nothing
- }
- }
- return 0;
- }
- }
-
- public static void exceptionLost() throws Exception {
- try {
- try {
- throw new Exception("a");
- } catch (Exception e) {
- System.out.println("In catch");
- throw e; // a
- } finally {
- System.out.println("In finally block");
-
-// if (true) {
-// throw new IOException("b");
-// }
- System.err.println("c");
- }
- } catch (IOException e) {
- System.err.println(e.getMessage());
- }
- }
-}
diff --git a/src/main/java/arhangel/dim/lections/jdbc/JdbcExample.java b/src/main/java/arhangel/dim/lections/jdbc/JdbcExample.java
deleted file mode 100644
index 268dee2..0000000
--- a/src/main/java/arhangel/dim/lections/jdbc/JdbcExample.java
+++ /dev/null
@@ -1,179 +0,0 @@
-package arhangel.dim.lections.jdbc;
-
-/**
- * Created by r.kildiev on 02.11.2015.
- */
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import arhangel.dim.core.User;
-
-public class JdbcExample {
-
- public static void main(String[] argv) throws SQLException, ClassNotFoundException {
-
- Class.forName("org.postgresql.Driver");
-
- Connection connection = DriverManager.getConnection("jdbc:postgresql://178.62.140.149:5432/main",
- "trackuser", "trackuser");
-
- Statement stmt;
- String sql;
-
- stmt = connection.createStatement();
- sql = "CREATE TABLE IF NOT EXISTS company" +
- "(ID INT PRIMARY KEY NOT NULL," +
- " NAME TEXT NOT NULL, " +
- " AGE INT NOT NULL, " +
- " ADDRESS CHAR(50), " +
- " SALARY REAL)";
- stmt.executeUpdate(sql);
- stmt.close();
-// c.close();
-
- connection.setAutoCommit(false);
-
- stmt = connection.createStatement();
- sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) VALUES (1, 'Paul', 32, 'California', 20000.00 );";
- stmt.executeUpdate(sql);
-
- sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) VALUES (2, 'Allen', 25, 'Texas', 15000.00 );";
- stmt.executeUpdate(sql);
-
- sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) VALUES (3, 'Teddy', 23, 'Norway', 20000.00 );";
- stmt.executeUpdate(sql);
-
- sql = "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 );";
- stmt.executeUpdate(sql);
-
- stmt.close();
- connection.commit();
-// c.close();
-
- stmt = connection.createStatement();
- ResultSet rs = stmt.executeQuery("SELECT * FROM COMPANY;");
- while (rs.next()) {
- int id = rs.getInt("id");
- String name = rs.getString("name");
- int age = rs.getInt("age");
- String address = rs.getString("address");
- float salary = rs.getFloat("salary");
- System.out.println("ID = " + id);
- System.out.println("NAME = " + name);
- System.out.println("AGE = " + age);
- System.out.println("ADDRESS = " + address);
- System.out.println("SALARY = " + salary);
- System.out.println();
- }
- rs.close();
- stmt.close();
-// c.close();
-
- stmt = connection.createStatement();
- sql = "UPDATE COMPANY SET SALARY = 25000.00 WHERE ID=1;";
- stmt.executeUpdate(sql);
- connection.commit();
-
- rs = stmt.executeQuery("SELECT * FROM COMPANY;");
- while (rs.next()) {
- int id = rs.getInt("id");
- String name = rs.getString("name");
- int age = rs.getInt("age");
- String address = rs.getString("address");
- float salary = rs.getFloat("salary");
- System.out.println("ID = " + id);
- System.out.println("NAME = " + name);
- System.out.println("AGE = " + age);
- System.out.println("ADDRESS = " + address);
- System.out.println("SALARY = " + salary);
- System.out.println();
- }
- rs.close();
- stmt.close();
-// c.close();
-
- stmt = connection.createStatement();
- sql = "DELETE FROM COMPANY WHERE ID=2;";
- stmt.executeUpdate(sql);
- connection.commit();
-
- rs = stmt.executeQuery("SELECT * FROM COMPANY;");
- while (rs.next()) {
- int id = rs.getInt("id");
- String name = rs.getString("name");
- int age = rs.getInt("age");
- String address = rs.getString("address");
- float salary = rs.getFloat("salary");
- System.out.println("ID = " + id);
- System.out.println("NAME = " + name);
- System.out.println("AGE = " + age);
- System.out.println("ADDRESS = " + address);
- System.out.println("SALARY = " + salary);
- System.out.println();
- }
- rs.close();
- stmt.close();
- connection.close();
-
-// PreparedStatement prepStmnt = c.prepareStatement("INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) "
-// + "VALUES (2, 'Allen', 25, 'Texas', 15000.00 );");
-// int parameterIndex = 234;
-// prepStmnt.setString(parameterIndex, "asd");
-// rs = prepStmnt.executeQuery();
-
-
-
- /**
- * Использование executor для запроса в базу
- */
- QueryExecutor exec = new QueryExecutor();
- List users = exec.execQuery(connection, "SELECT * FROM users;", (rset) -> {
- System.out.println("handle:");
- List data = new ArrayList<>();
- while (rset.next()) {
- User user = new User();
- user.setName(rset.getString(2));
- data.add(user);
- }
- return data;
- });
-
- System.out.println(users.toString());
-
-
- /**
- * Использование prepared executor для запроса в базу
- */
- Map prepared = new HashMap<>();
- prepared.put(1, "John");
-
- users = exec.execQuery(connection, "SELECT * FROM users WHERE name = ?;", prepared, (rset) -> {
- System.out.println("handle:");
- List data = new ArrayList<>();
- while (rset.next()) {
- User user = new User();
- user.setName(rset.getString(2));
- data.add(user);
- }
- return data;
- });
-
- System.out.println(users.toString());
-
-
-
-
-
- }
-
-
-
-}
diff --git a/src/main/java/arhangel/dim/lections/jdbc/QueryExecutor.java b/src/main/java/arhangel/dim/lections/jdbc/QueryExecutor.java
deleted file mode 100644
index 6e5e512..0000000
--- a/src/main/java/arhangel/dim/lections/jdbc/QueryExecutor.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package arhangel.dim.lections.jdbc;
-
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.Map;
-
-/**
- *
- */
-public class QueryExecutor {
-
- // Простой запрос
- public T execQuery(Connection connection, String query, ResultHandler handler) throws SQLException {
- Statement stmt = connection.createStatement();
- stmt.execute(query);
- ResultSet result = stmt.getResultSet();
- T value = handler.handle(result);
- result.close();
- stmt.close();
-
- return value;
- }
-
- // Подготовленный запрос
- public T execQuery(Connection connection, String query, Map args, ResultHandler handler) throws SQLException {
- PreparedStatement stmt = connection.prepareStatement(query);
- for (Map.Entry entry : args.entrySet()) {
- stmt.setObject(entry.getKey(), entry.getValue());
- }
- ResultSet rs = stmt.executeQuery();
- T value = handler.handle(rs);
- rs.close();
- stmt.close();
- return value;
- }
-
- // Также нужно реализовать Update запросы
-
-}
diff --git a/src/main/java/arhangel/dim/lections/objects/AServer.java b/src/main/java/arhangel/dim/lections/objects/AServer.java
deleted file mode 100644
index 7e53ad2..0000000
--- a/src/main/java/arhangel/dim/lections/objects/AServer.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package arhangel.dim.lections.objects;
-
-/**
- *
- */
-public abstract class AServer {
-
- protected abstract boolean validate(String[] params);
-
- protected abstract void processContent();
-
- protected String onError() {
- return "Failed to parse request";
- }
-
- public void doGet(String request) {
- String[] parameters = parseParameters(request);
- if (validate(parameters)) {
- processContent();
- } else {
- onError();
- }
- }
-
- private String[] parseParameters(String request) {
- // разбираем строку параметров
- return null;
- }
-}
diff --git a/src/main/java/arhangel/dim/lections/objects/AbstractExample.java b/src/main/java/arhangel/dim/lections/objects/AbstractExample.java
deleted file mode 100644
index ac55544..0000000
--- a/src/main/java/arhangel/dim/lections/objects/AbstractExample.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package arhangel.dim.lections.objects;
-
-/**
- *
- */
-public class AbstractExample {
-
- public static void main(String[] args) {
-
- // Создаем класс-потомок
- AServer imageServer = new ImageServer();
- imageServer.processContent();
-
- // Нельзя создать инстанс абстрактного класса
- // AServer aserver = new AServer();
-
-
- // Можно создать анонимный класс
- AServer server = new AServer() {
- @Override
- protected boolean validate(String[] params) {
- return false;
- }
-
- @Override
- protected void processContent() {
-
- }
- };
- }
-
-}
-
-
diff --git a/src/main/java/arhangel/dim/lections/objects/Button.java b/src/main/java/arhangel/dim/lections/objects/Button.java
deleted file mode 100644
index c202d3c..0000000
--- a/src/main/java/arhangel/dim/lections/objects/Button.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package arhangel.dim.lections.objects;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- *
- */
-public class Button {
- private ClickListener[] listeners = new ClickListener[10];
- private int count = 0;
-
- // закоментирован вариант с List
- //private List listenerList = new ArrayList<>();
-
- // Добавляем себе подписчиков
- public void addListener(ClickListener listener) {
- listeners[count++] = listener;
-
- //listenerList.add(listener);
- }
-
- // На кнопку кто-то нажал и теперь все об этом узнают
- public void click() {
- for (int i = 0; i < count; i++) {
- listeners[i].onClick();
- }
-
-// for (ClickListener listener : listenerList) {
-// listener.onClick();
-// }
- }
-
-
-
-}
diff --git a/src/main/java/arhangel/dim/lections/objects/ClickListener.java b/src/main/java/arhangel/dim/lections/objects/ClickListener.java
deleted file mode 100644
index 3d4bc7b..0000000
--- a/src/main/java/arhangel/dim/lections/objects/ClickListener.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package arhangel.dim.lections.objects;
-
-/**
- *
- */
-public interface ClickListener {
-
- // do smth on click
- void onClick();
-}
diff --git a/src/main/java/arhangel/dim/lections/objects/ImageServer.java b/src/main/java/arhangel/dim/lections/objects/ImageServer.java
deleted file mode 100644
index 8c8c4bb..0000000
--- a/src/main/java/arhangel/dim/lections/objects/ImageServer.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package arhangel.dim.lections.objects;
-
-/**
- *
- */
-public class ImageServer extends AServer {
- @Override
- protected boolean validate(String[] params) {
- return params.length > 0 && params[0].equals("imageId");
- }
-
- @Override
- protected void processContent() {
- // Загрузим картинку и отдадим ее пользователю
- }
-
- @Override
- protected String onError() {
- return "Failed to parse ImageId";
- }
-}
-
diff --git a/src/main/java/arhangel/dim/lections/objects/LinkageTest.java b/src/main/java/arhangel/dim/lections/objects/LinkageTest.java
deleted file mode 100644
index 0dba290..0000000
--- a/src/main/java/arhangel/dim/lections/objects/LinkageTest.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package arhangel.dim.lections.objects;
-
-/**
- *
- */
-public class LinkageTest {
-
- static class Parent {
- void test() {
- System.out.println("parent::test()");
- }
- }
-
- static class Child extends Parent {
- @Override
- void test() {
- System.out.println("child::test()");
- }
- }
-
- static void use(Parent item) {
- System.out.println("use::parent");
- item.test();
- }
-
- static void use(Child item) {
- System.out.println("use::child");
- item.test();
- }
-
- public static void main(String[] args) {
- Parent item = new Child();
- use(item);
-
- }
-
-}
diff --git a/src/main/java/arhangel/dim/lections/objects/ListenerDemo.java b/src/main/java/arhangel/dim/lections/objects/ListenerDemo.java
deleted file mode 100644
index 264e055..0000000
--- a/src/main/java/arhangel/dim/lections/objects/ListenerDemo.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package arhangel.dim.lections.objects;
-
-/**
- *
- */
-public class ListenerDemo {
-
- public static void main(String[] args) {
-
- Canvas canvas = new Canvas();
- Pentagon pentagon = new Pentagon();
-
- Button redButton = new Button();
- redButton.addListener(canvas);
- redButton.addListener(pentagon);
- redButton.addListener(new Ussr());
-
- redButton.click();
- }
-
- static class Canvas implements ClickListener {
-
- // Много методов про отрисовку экрана
-
- @Override
- public void onClick() {
- System.out.println("CANVAS: Button was pressed");
- }
- }
-
- static class Pentagon implements ClickListener {
-
- public void alarm() {
- System.out.println("ALARM!");
- }
-
- @Override
- public void onClick() {
- alarm();
- }
- }
-
- static class Ussr implements ClickListener {
- private void launchRocket() {
- System.out.println("Ракеты запущены, командир!");
- }
-
- @Override
- public void onClick() {
- launchRocket();
- }
- }
-
-}
diff --git a/src/main/java/arhangel/dim/lections/objects/LoaderDemo.java b/src/main/java/arhangel/dim/lections/objects/LoaderDemo.java
deleted file mode 100644
index 3d0a6d0..0000000
--- a/src/main/java/arhangel/dim/lections/objects/LoaderDemo.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package arhangel.dim.lections.objects;
-
-import java.net.URI;
-
-/**
- *
- */
-public class LoaderDemo {
-
- public static void main(String[] args) throws Exception {
- //Loader loader = new XmlLoader();
- Loader loader = new NetLoader();
- Resource resource = loader.load(new URI("test-path"));
- }
-}
-
-class Resource {
- // класс с настройками
-}
-
-interface Loader {
- Resource load(URI uri);
-}
-
-class XmlLoader implements Loader {
- @Override
- public Resource load(URI uri) {
- // read XML and parse
- return new Resource();
- }
-}
-
-class NetLoader implements Loader {
- @Override
- public Resource load(URI uri) {
- // read Resources from internet
- return new Resource();
- }
-}
-
diff --git a/src/main/java/arhangel/dim/lections/objects/Polimorf.java b/src/main/java/arhangel/dim/lections/objects/Polimorf.java
deleted file mode 100644
index 405ed1b..0000000
--- a/src/main/java/arhangel/dim/lections/objects/Polimorf.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package arhangel.dim.lections.objects;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- *
- */
-public class Polimorf {
-
- private static Logger log = LoggerFactory.getLogger(Polimorf.class);
-
- static class Parent {
- void test() {
- System.out.println("parent::test()");
- }
-
- void testParent() {
- System.out.println("parent::testParent()");
- }
- }
-
- static class Child extends Parent {
- @Override
- void test() {
- System.out.println("child::test()");
- }
-
- void testChild() {
- System.out.println("child::testParent()");
- }
- }
-
- public static void main(String[] args) {
- Parent item = new Child();
-
- System.out.println("===Parent -> Child===");
- // Late binding - invoke Child impl
- item.test();
- item.testParent();
- // No such method in Parent
- //item.testChild();
-
- System.out.println("===Child -> Child===");
- Child other = new Child();
- other.test();
- other.testChild();
- other.testParent();
-
- System.out.println("===Collection===");
- List list = new ArrayList<>();
- list.add(new Child());
- list.add(new Parent());
-
- // Using for loop (old!)
- for (Parent p : list) {
- p.test();
- }
-
- // Using stream
- //list.stream().forEach(p -> p.test());
-
- // Using method references
- // list.stream().forEach(Parent::test);
-
-
- }
-}
diff --git a/src/main/java/arhangel/dim/lections/objects/StaticDemo.java b/src/main/java/arhangel/dim/lections/objects/StaticDemo.java
deleted file mode 100644
index ed20f23..0000000
--- a/src/main/java/arhangel/dim/lections/objects/StaticDemo.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package arhangel.dim.lections.objects;
-
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- *
- */
-public class StaticDemo {
-
- private static Logger log = LoggerFactory.getLogger(StaticDemo.class);
-
- public static void main(String[] args) {
- log.info("Account counter: " + Account.idCounter);
-
- int current = Account.idCounter;
- // Запрещено, id - это поле экземпляра, его нужно создать и инициализировать
- //int id = Account.id;
-
- for (int i = 0; i < 5; i++) {
- Account acc = new Account();
- log.info(acc.toString());
- }
-
- Account acc = null;
-
- // Так делать нехорошо!
- acc.idCounter = 10;
-
- // А так можно
- Account.idCounter = 10;
-
-
- }
-}
-
-class Account {
-
- static int idCounter = 0;
- int id;
-
- public Account() {
- id = idCounter++;
- }
-
- public static Account createAccount() {
- System.out.println("Account created");
- return new Account();
- }
-
- @Override
- public String toString() {
- return "Account{" +
- "id=" + id +
- '}';
- }
-}
-
-class ExtAccount extends Account {
- public static Account createAccount() {
- System.out.println("Ext Account created");
- return new Account();
- }
-}
diff --git a/src/main/java/arhangel/dim/lections/reflection/Reflect.java b/src/main/java/arhangel/dim/lections/reflection/Reflect.java
deleted file mode 100644
index a23bf75..0000000
--- a/src/main/java/arhangel/dim/lections/reflection/Reflect.java
+++ /dev/null
@@ -1,155 +0,0 @@
-package arhangel.dim.lections.reflection;
-
-import java.io.Serializable;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-
-/**
- *
- */
-class Test implements Serializable, Cloneable {
- private int field;
-
- public Test() {
-
- }
-
- public Test(Object field) { }
-
- @Deprecated
- protected static void method(String[] params) { }
-
-
- public void foo() {
- System.out.println("FOO");
- }
-
- @Override
- public String toString() {
- return "Test{" +
- "field=" + field +
- '}';
- }
-}
-
-public class Reflect {
- public static void main(String[] args) throws Exception {
- Class clazz = Test.class;
- Test test = (Test) clazz.newInstance();
-
- clazz.getConstructors();
-
- // вызвать метод по имени у заданного объекта
- Method method = clazz.getMethod("foo");
- System.out.println(method.toString());
- method.invoke(test);
-
- // установить поле по имени у заданного объекта
- Field field0 = clazz.getDeclaredField("field");
- field0.setAccessible(true);
- field0.set(test, 100);
- System.out.println(test);
-
- // выводим название пакета
- Package pack = clazz.getPackage();
- System.out.println("package " + pack.getName() + ";");
-
- // начинаем декларацию класса с модификаторов
- int modifiers = clazz.getModifiers();
- System.out.print(getModifiers(modifiers));
- // выводим название класса
- System.out.print("class " + clazz.getSimpleName() + " ");
-
- // выводим название родительского класса
- System.out.print("extends " + clazz.getSuperclass().getSimpleName() + " ");
-
- // выводим интерфейсы, которые реализует класс
- Class[] interfaces = clazz.getInterfaces();
- for (int i = 0, size = interfaces.length; i < size; i++) {
- System.out.print(i == 0 ? "implements " : ", ");
- System.out.print(interfaces[i].getSimpleName());
- }
- System.out.println(" {");
-
- // выводим поля класса
- Field[] fields = clazz.getDeclaredFields();
- for (Field field : fields) {
- System.out.println("\t" + getModifiers(field.getModifiers()) +
- getType(field.getType()) + " " + field.getName() + ";");
- }
-
- // выводим констукторы класса
- Constructor[] constructors = clazz.getDeclaredConstructors();
- for (Constructor c : constructors) {
- System.out.print("\t" + getModifiers(c.getModifiers()) +
- clazz.getSimpleName() + "(");
- System.out.print(getParameters(c.getParameterTypes()));
- System.out.println(") { }");
- }
-
- // выводим методы класса
- Method[] methods = clazz.getDeclaredMethods();
- for (Method m : methods) {
- // получаем аннотации
- Annotation[] annotations = m.getAnnotations();
- System.out.print("\t");
- for (Annotation a : annotations) {
- System.out.print("@" + a.annotationType().getSimpleName() + " ");
- }
- System.out.println();
-
- System.out.print("\t" + getModifiers(m.getModifiers()) +
- getType(m.getReturnType()) + " " + m.getName() + "(");
- System.out.print(getParameters(m.getParameterTypes()));
- System.out.println(") { }");
- }
-
- System.out.println("}");
-
-
- }
-
- static String getModifiers(int mod) {
- String modifiers = "";
- if (Modifier.isPublic(mod)) {
- modifiers += "public ";
- }
- if (Modifier.isProtected(mod)) {
- modifiers += "protected ";
- }
- if (Modifier.isPrivate(mod)) {
- modifiers += "private ";
- }
- if (Modifier.isStatic(mod)) {
- modifiers += "static ";
- }
- if (Modifier.isAbstract(mod)) {
- modifiers += "abstract ";
- }
-
- return modifiers;
- }
-
- static String getType(Class clazz) {
- String type = clazz.isArray() ? clazz.getComponentType().getSimpleName()
- : clazz.getSimpleName();
- if (clazz.isArray()) {
- type += "[]";
- }
- return type;
- }
-
- static String getParameters(Class[] params) {
- String param = "";
- for (int i = 0, size = params.length; i < size; i++) {
- if (i > 0) {
- param += ", ";
- }
- param += getType(params[i]) + " param" + i;
- }
- return param;
- }
-}
diff --git a/src/main/java/arhangel/dim/lections/socket/Client.java b/src/main/java/arhangel/dim/lections/socket/Client.java
deleted file mode 100644
index 1c794a2..0000000
--- a/src/main/java/arhangel/dim/lections/socket/Client.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package arhangel.dim.lections.socket;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.Socket;
-
-/**
- * Клиентская часть
- */
-public class Client {
-
- public static final int PORT = 19000;
- public static final String HOST = "localhost";
-
- public static void main(String[] args) {
-
- Socket socket = null;
- try {
- socket = new Socket(HOST, PORT);
-
- try (InputStream in = socket.getInputStream();
- OutputStream out = socket.getOutputStream()) {
-
- String line = "Hello!";
- out.write(line.getBytes());
- out.flush();
-
- byte[] data = new byte[32 * 1024];
- int readBytes = in.read(data);
-
- System.out.printf("Server> %s", new String(data, 0, readBytes));
-
- }
-
- } catch (IOException e) {
- e.printStackTrace();
- // exit, failed to open socket
- } finally {
- IoUtil.closeQuietly(socket);
- }
- }
-
-
-
-}
diff --git a/src/main/java/arhangel/dim/lections/socket/Server.java b/src/main/java/arhangel/dim/lections/socket/Server.java
deleted file mode 100644
index 09e0fed..0000000
--- a/src/main/java/arhangel/dim/lections/socket/Server.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package arhangel.dim.lections.socket;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.ServerSocket;
-import java.net.Socket;
-
-
-/**
- * Обработка подключений
- */
-public class Server {
-
- public static final int PORT = 19000;
-
- public static void main(String[] args) {
-
- ServerSocket serverSocket = null;
- try {
- serverSocket = new ServerSocket(PORT);
-
- System.out.println("Started, waiting for connection");
-
- Socket socket = serverSocket.accept();
-
- System.out.println("Accepted. " + socket.getInetAddress());
-
- try (InputStream in = socket.getInputStream();
- OutputStream out = socket.getOutputStream()) {
-
-
- byte[] buf = new byte[32 * 1024];
- int readBytes = in.read(buf);
- String line = new String(buf, 0, readBytes);
- System.out.printf("Client>%s", line);
-
- out.write(line.getBytes());
- out.flush();
- }
-
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- IoUtil.closeQuietly(serverSocket);
- }
- }
-}
diff --git a/src/main/java/arhangel/dim/lections/threads/DeadLock.java b/src/main/java/arhangel/dim/lections/threads/DeadLock.java
deleted file mode 100644
index c47e347..0000000
--- a/src/main/java/arhangel/dim/lections/threads/DeadLock.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package arhangel.dim.lections.threads;
-
-
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- *
- */
-public class DeadLock {
- static Logger logger = LoggerFactory.getLogger(DeadLock.class);
- Lock lock = new ReentrantLock();
-
- public static void main(String[] args) {
-
- final Account a1 = new Account(1);
- a1.sum = 100;
- final Account a2 = new Account(2);
- a2.sum = 300;
-
- Thread t1 = new Thread(() -> {
- Account.transact(a1, a2, 10);
- }, "");
-
- Thread t2 = new Thread(() -> {
- Account.transact(a2, a1, 20);
- }, "");
-
- t1.start();
- t2.start();
- }
-
- static class Account {
- int sum;
- int id;
-
- public Account(int id) {
- this.id = id;
- }
-
- static void transact(final Account from, final Account to, int amount) {
- Account lock1;
- Account lock2;
-
-// lock1 = from;
-// lock2 = to;
-
- if (from.id < to.id) {
- lock1 = from;
- lock2 = to;
- } else {
- lock1 = to;
- lock2 = from;
- }
-
- synchronized (lock1) {
- logger.info("Lock1({}) was acquired by thread {}. Waiting for lock2({}), " +
- "lock1.id, Thread.currentThread().getName(), lock2.id");
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- synchronized (lock2) {
- logger.info("Lock2({}) was acquired by thread {}. Waiting for lock1({}), " +
- "lock2.id, Thread.currentThread().getName(), lock1.id");
- from.sum -= amount;
- to.sum += amount;
- }
- }
- }
- }
-
-}
diff --git a/src/main/java/arhangel/dim/lections/threads/Monitor.java b/src/main/java/arhangel/dim/lections/threads/Monitor.java
deleted file mode 100644
index 8c985c4..0000000
--- a/src/main/java/arhangel/dim/lections/threads/Monitor.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package arhangel.dim.lections.threads;
-
-/**
- *
- */
-public class Monitor {
-
- private final Object lockObject = new Object();
-
- private final Object anotherLockObject = new Object();
-
- int counter = 0;
-
- public void doChange() {
- synchronized (lockObject) {
- counter++;
- }
- }
-
- public void doAnotherChange() {
- synchronized (anotherLockObject) {
- counter++;
- }
- }
-
- public static void main(String[] args) {
- Monitor monitor = new Monitor();
-
- new Thread(() -> {
- for (int i = 0; i < 100_000; i++) {
- monitor.doChange();
- }
- }).start();
-
- new Thread(() -> {
- for (int i = 0; i < 100_000; i++) {
- monitor.doAnotherChange();
- }
- }).start();
-
- System.out.println(monitor.counter);
- }
-
-
-}
diff --git a/src/main/java/arhangel/dim/lections/threads/MyThread.java b/src/main/java/arhangel/dim/lections/threads/MyThread.java
deleted file mode 100644
index c8db1e4..0000000
--- a/src/main/java/arhangel/dim/lections/threads/MyThread.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package arhangel.dim.lections.threads;
-
-import java.util.concurrent.TimeUnit;
-
-class MyThread extends Thread {
-
- private String name;
-
- public MyThread(String name) {
- this.name = name;
- }
-
- @Override
- public void run() {
- System.out.println("Thread " + name + ": started");
- try {
- for (int i = 0; i < 5; i++) {
- System.out.println("MyThread " + name + " : " + i);
- TimeUnit.SECONDS.sleep(1);
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("MyThread: finished");
- }
-}
diff --git a/src/main/java/arhangel/dim/lections/threads/Pool.java b/src/main/java/arhangel/dim/lections/threads/Pool.java
deleted file mode 100644
index 325f1c4..0000000
--- a/src/main/java/arhangel/dim/lections/threads/Pool.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package arhangel.dim.lections.threads;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-
-/**
- *
- */
-public class Pool {
-
- public static void main(String[] args) throws Exception {
-
- int cores = Runtime.getRuntime().availableProcessors();
- System.out.println("Processors available: " + cores);
- ExecutorService service = Executors.newFixedThreadPool(2);
-
- List futures = new ArrayList<>();
-
- for (int i = 0; i < 4; i++) {
-// Future future = service.submit(new MyThread("t#" + i));
- Future future = service.submit(new Task(i * 2));
- futures.add(future);
- }
-
- System.out.println("1) ========================");
-
- for (Future f : futures) {
- System.out.println("result: " + f.get());
- }
-
- System.out.println("2) ========================");
- }
-
- static class Task implements Callable {
-
- int num;
-
- public Task(int num) {
- this.num = num;
- }
-
- @Override
- public Integer call() throws Exception {
- int acc = 0;
- try {
- for (int i = 0; i < num; i++) {
- TimeUnit.SECONDS.sleep(1);
- acc += i;
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- return acc;
- }
- }
-
-}
diff --git a/src/main/java/arhangel/dim/lections/threads/SimpleThread.java b/src/main/java/arhangel/dim/lections/threads/SimpleThread.java
deleted file mode 100644
index 141a3d5..0000000
--- a/src/main/java/arhangel/dim/lections/threads/SimpleThread.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package arhangel.dim.lections.threads;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- *
- */
-public class SimpleThread {
-
-
-
- public static void main(String[] args) throws Exception {
- inParallel();
-// start();
-// join();
- }
-
- static void inParallel() throws Exception {
- Thread t1 = new MyThread("inParallel");
-
- // Запуск кода в новом треде
- System.out.println("Starting thread");
- t1.start();
-
- for (int i = 0; i < 5; i++) {
- System.out.println("Main:" + i);
- TimeUnit.SECONDS.sleep(2);
- }
- System.out.println("Main thread finished");
- }
-
-
- static void start() {
- Thread t1 = new MyThread("simpleThread");
-
- // Запуск кода в новом треде
- System.out.println("Starting thread");
- t1.start();
-
- // А здесь?
-// System.out.println("Running");
-// t1.run();
-
- System.out.println("Error:");
- // Нельзя запустить поток еще раз
- // Почему?
- //t1.start();
- }
-
- static void join() throws Exception {
- Thread thread = new MyThread("joinThread");
- System.out.println("Starting thread...");
- thread.start();
- System.out.println("Joining");
- //t.join();
- System.out.println("Joined");
-
-
- }
-
-}
diff --git a/src/main/java/arhangel/dim/lections/threads/StopThread.java b/src/main/java/arhangel/dim/lections/threads/StopThread.java
deleted file mode 100644
index 0bc5808..0000000
--- a/src/main/java/arhangel/dim/lections/threads/StopThread.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package arhangel.dim.lections.threads;
-
-import java.util.Scanner;
-import java.util.concurrent.TimeUnit;
-
-/**
- *
- */
-public class StopThread {
-
- static class FlagThread extends Thread {
- private volatile boolean pleaseStop;
-
- @Override
- public void run() {
- while (!pleaseStop) {
- try {
- System.out.println("Thread::sleep()");
- TimeUnit.SECONDS.sleep(100);
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
- }
-
- public void stopThread() {
- System.out.println("Stopping...");
- pleaseStop = true;
- }
- }
-
- static class InterThread extends Thread {
- @Override
- public void run() {
- while (!Thread.currentThread().isInterrupted()) {
- try {
- System.out.println("Thread::sleep()");
- TimeUnit.SECONDS.sleep(1);
- } catch (InterruptedException e) {
- e.printStackTrace();
- Thread.currentThread().interrupt();
- }
- }
- }
- }
-
- static class DummyThread extends Thread {
- @Override
- public void run() {
- while (true) {
- System.out.println("q");
-// try {
-// System.out.println("Thread::sleep()");
-// TimeUnit.SECONDS.sleep(1);
-// } catch (InterruptedException e) {
-// }
- }
- }
- }
-
- public static void flagThread() {
- FlagThread flagThread = new FlagThread();
- flagThread.start();
-
- Scanner scanner = new Scanner(System.in);
- scanner.next();
- flagThread.stopThread();
- }
-
- public static void interruptThread() {
- Thread thread = new InterThread();
- thread.start();
-
- Scanner scanner = new Scanner(System.in);
- scanner.next();
- thread.interrupt();
- }
-
- public static void dummyThread() {
- Thread thread = new DummyThread();
- thread.start();
-
- Scanner scanner = new Scanner(System.in);
- scanner.next();
- thread.interrupt();
- }
-
- public static void main(String[] args) throws Exception {
- //flagThread();
- //interruptThread();
- dummyThread();
- }
-}
diff --git a/src/main/java/arhangel/dim/lections/threads/counting/AtomicCounter.java b/src/main/java/arhangel/dim/lections/threads/counting/AtomicCounter.java
deleted file mode 100644
index fdac6db..0000000
--- a/src/main/java/arhangel/dim/lections/threads/counting/AtomicCounter.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package arhangel.dim.lections.threads.counting;
-
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- *
- */
-public class AtomicCounter implements Counter {
-
- private AtomicLong val = new AtomicLong(0);
-
- @Override
- public long inc() {
- return val.getAndIncrement();
- }
-}
diff --git a/src/main/java/arhangel/dim/lections/threads/counting/Counter.java b/src/main/java/arhangel/dim/lections/threads/counting/Counter.java
deleted file mode 100644
index 95b720b..0000000
--- a/src/main/java/arhangel/dim/lections/threads/counting/Counter.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package arhangel.dim.lections.threads.counting;
-
-/**
- *
- */
-public interface Counter {
-
- long inc();
-}
diff --git a/src/main/java/arhangel/dim/lections/threads/counting/CounterTest.java b/src/main/java/arhangel/dim/lections/threads/counting/CounterTest.java
deleted file mode 100644
index 089ba4b..0000000
--- a/src/main/java/arhangel/dim/lections/threads/counting/CounterTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package arhangel.dim.lections.threads.counting;
-
-/**
- *
- */
-public class CounterTest {
-
- static class Sequencer extends Thread {
- private Counter counter;
-
- public Sequencer(Counter counter) {
- this.counter = counter;
- }
-
- @Override
- public void run() {
- for (int i = 0; i < 100_000; i++) {
- counter.inc();
- }
- }
- }
-
- static class UnsafeSequencer extends Thread {
- private LockCounter counter;
-
- public UnsafeSequencer(LockCounter counter) {
- this.counter = counter;
- }
-
- @Override
- public void run() {
- for (int i = 0; i < 100_000; i++) {
- counter.incUnsafe();
- }
- }
- }
-
- public static void main(String[] args) throws Exception {
- //testCounter();
- testSafeUnsafe();
- }
-
- public static void testCounter() throws Exception {
- final int threadNum = 2;
- //Counter counter = new SimpleCounter();
- Counter counter = new AtomicCounter();
- //LockCounter counter = new LockCounter();
- Thread[] threads = new Thread[threadNum];
- for (int i = 0; i < threadNum; i++) {
- Thread thread = new Sequencer(counter);
- threads[i] = thread;
- thread.start();
- }
-
- for (Thread t : threads) {
- t.join();
- }
-
- System.out.printf("Threads: %d\nCounter: %d", threadNum, counter.inc());
- }
-
- public static void testSafeUnsafe() throws Exception {
-
- final int threadNum = 2;
- //Counter counter = new SimpleCounter();
- //Counter counter = new AtomicCounter();
- LockCounter counter = new LockCounter();
- Thread[] threads = new Thread[threadNum];
- for (int i = 0; i < threadNum; i++) {
- Thread thread = new Sequencer(counter);
- threads[i] = thread;
- thread.start();
- }
- Thread unsafe = new UnsafeSequencer(counter);
- unsafe.start();
-
- for (Thread t : threads) {
- t.join();
- }
-
- unsafe.join();
-
- System.out.printf("Threads: %d\nCounter: %d", threadNum, counter.inc());
- }
-
-
-}
diff --git a/src/main/java/arhangel/dim/lections/threads/counting/LockCounter.java b/src/main/java/arhangel/dim/lections/threads/counting/LockCounter.java
deleted file mode 100644
index 608d5ec..0000000
--- a/src/main/java/arhangel/dim/lections/threads/counting/LockCounter.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package arhangel.dim.lections.threads.counting;
-
-/**
- * реализация счетчика через лок
- */
-public class LockCounter implements Counter {
-
- private long counter;
-
- public synchronized long inc() {
- return counter++;
- }
-
- public long incUnsafe() {
- return counter++;
- }
-
-
-}
diff --git a/src/main/java/arhangel/dim/lections/threads/counting/SimpleCounter.java b/src/main/java/arhangel/dim/lections/threads/counting/SimpleCounter.java
deleted file mode 100644
index 03c221b..0000000
--- a/src/main/java/arhangel/dim/lections/threads/counting/SimpleCounter.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package arhangel.dim.lections.threads.counting;
-
-/**
- *
- */
-public class SimpleCounter implements Counter {
- private long val;
-
- public long inc() {
- return val++;
- }
-
-}
diff --git a/src/main/java/arhangel/dim/lections/threads/queueu/BlockingQueue.java b/src/main/java/arhangel/dim/lections/threads/queueu/BlockingQueue.java
deleted file mode 100644
index 27eb325..0000000
--- a/src/main/java/arhangel/dim/lections/threads/queueu/BlockingQueue.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package arhangel.dim.lections.threads.queueu;
-
-/**
- *
- */
-public interface BlockingQueue {
-
- /**
- *
- * @param e the element to add
- */
- void put(E elem) throws InterruptedException;
-
- /**
- *
- * @return the head element
- */
- E take() throws InterruptedException;
-}
diff --git a/src/main/java/arhangel/dim/lections/threads/queueu/ListBlockingQueue.java b/src/main/java/arhangel/dim/lections/threads/queueu/ListBlockingQueue.java
deleted file mode 100644
index 6b8b083..0000000
--- a/src/main/java/arhangel/dim/lections/threads/queueu/ListBlockingQueue.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package arhangel.dim.lections.threads.queueu;
-
-import java.util.LinkedList;
-
-/**
- *
- */
-public class ListBlockingQueue implements BlockingQueue {
-
- public static final int DEFAULT_CAPACITY = 10;
-
- private int capacity;
- private LinkedList list = new LinkedList<>();
-
- public ListBlockingQueue() {
- capacity = DEFAULT_CAPACITY;
- }
-
- public ListBlockingQueue(int capacity) {
- this.capacity = capacity;
- }
-
- @Override
- public void put(E elem) throws InterruptedException {
-
- /*
- Внутри критической секции пытаемся поместить элемент в очередь
- Если очередь полная isFull==true то блокируемся на wait() пока условие не будет выполнено
- */
- }
-
- @Override
- public E take() throws InterruptedException {
-
- /*
- Внутри критической секции пытаемся достать элемент из очереди
- Если очередь пустая isEmpty == true то блокируемся на wait() пока условие не будет выполнено
- */
- return null;
- }
-
- private boolean isFull() {
- return list.size() == capacity;
- }
-
- private boolean isEmpty() {
- return list.size() == 0;
- }
-
-}
diff --git a/src/main/java/arhangel/dim/lections/threads/queueu/ProducerConsumer.java b/src/main/java/arhangel/dim/lections/threads/queueu/ProducerConsumer.java
deleted file mode 100644
index 1b60c9c..0000000
--- a/src/main/java/arhangel/dim/lections/threads/queueu/ProducerConsumer.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package arhangel.dim.lections.threads.queueu;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ProducerConsumer {
-
- static Logger log = LoggerFactory.getLogger(ProducerConsumer.class);
-
- static boolean isReady = false;
-
- static class Producer extends Thread {
- private final Object lock;
-
- public Producer(Object lock) {
- this.lock = lock;
- }
-
- @Override
- public void run() {
- log.info("[PRODUCER] Preparing data...");
- try {
- sleep(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- log.info("[PRODUCER] Data prepared. Notify All!");
-
- isReady = true;
- synchronized (lock) {
- lock.notifyAll();
- }
- }
-
- }
-
- static class Consumer extends Thread {
- private final Object lock;
-
- public Consumer(Object lock) {
- this.lock = lock;
- }
-
- @Override
- public void run() {
-
- synchronized (lock) {
- log.info("[CONSUMER] Waiting for data...");
-
- // Если данные еще не готовы
- while (!isReady) {
- try {
- // ждем
- lock.wait();
- // как только пробудились, заново проверяем состояние данных
- // если они не готовы (или кто-то уже их поменял), то снова ждем
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- log.info("[CONSUMER] Data received");
- }
- }
-
- }
-
- public static void main(String[] args) {
- Object lock = new Object();
- new Consumer(lock).start();
- new Producer(lock).start();
- }
-}
diff --git a/src/main/java/arhangel/dim/server/CommandHandler.java b/src/main/java/arhangel/dim/server/CommandHandler.java
new file mode 100644
index 0000000..1398c29
--- /dev/null
+++ b/src/main/java/arhangel/dim/server/CommandHandler.java
@@ -0,0 +1,79 @@
+package arhangel.dim.server;
+
+import arhangel.dim.core.authorization.Authorize;
+import arhangel.dim.core.commands.Command;
+import arhangel.dim.core.message.AnswerMessage;
+import arhangel.dim.core.message.Message;
+import arhangel.dim.core.message.Protocol;
+import arhangel.dim.core.message.SerializationProtocol;
+import arhangel.dim.core.session.Session;
+import arhangel.dim.core.session.SessionManager;
+import arhangel.dim.core.store.DataStore;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Map;
+
+/**
+ * Обработчик команд, поступающих от определённого клиента
+ */
+public class CommandHandler implements Runnable {
+ /**
+ * Потоки для общения с клиентом
+ */
+ private DataInputStream reader;
+ private DataOutputStream writer;
+
+ /**
+ * Список всех баз данных, требуемых для работы
+ */
+ private DataStore dataStore;
+
+ /**
+ * Список сессий.
+ */
+ private SessionManager sessionManager;
+
+ public CommandHandler(InputStream reader, OutputStream writer, DataStore dataStore, SessionManager sessionManager) {
+ this.sessionManager = sessionManager;
+ this.reader = new DataInputStream(reader);
+ this.writer = new DataOutputStream(writer);
+ this.dataStore = dataStore;
+ }
+
+ @Override
+ public void run() {
+ try {
+ Map commands = dataStore.getCommandsStore();
+ Authorize service = new Authorize(dataStore.getUserStore());
+ Session session = new Session(reader, writer, service, dataStore, sessionManager);
+ sessionManager.addSession(session);
+ Protocol answerProtocol = new SerializationProtocol<>();
+ Protocol readProtocol = new SerializationProtocol<>();
+ while (true) {
+ byte[] readData = new byte[1024 * 64];
+ reader.read(readData);
+ Message received = readProtocol.decode(readData);
+ String command = received.getMessage();
+ if (command.equals("/exit")) {
+ break;
+ }
+ String[] parsedCommand = command.split("\\s+");
+ Command commandClass = commands.get(parsedCommand[0]);
+ if (commandClass == null) {
+ String str = "Wrong command";
+ AnswerMessage answer = new AnswerMessage(str , AnswerMessage.Value.ERROR);
+ writer.write(answerProtocol.encode(answer));
+ continue;
+ }
+ commandClass.run(parsedCommand, session);
+
+ }
+
+ } catch (Exception e) {
+ System.err.println("Exception in reading command " + e.toString());
+ }
+ }
+}
diff --git a/src/main/java/arhangel/dim/server/MultiThreadServer.java b/src/main/java/arhangel/dim/server/MultiThreadServer.java
new file mode 100644
index 0000000..635ea23
--- /dev/null
+++ b/src/main/java/arhangel/dim/server/MultiThreadServer.java
@@ -0,0 +1,112 @@
+package arhangel.dim.server;
+
+import arhangel.dim.container.Container;
+import arhangel.dim.container.beans.WebConnection;
+import arhangel.dim.core.store.DataBaseUserStore;
+import arhangel.dim.core.jdbc.DataBaseOrganizer;
+import arhangel.dim.core.store.DataBaseChatStore;
+import arhangel.dim.core.session.SessionManager;
+import arhangel.dim.core.store.DataStore;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Многопоточный сервер
+ */
+public class MultiThreadServer implements Runnable, AutoCloseable {
+
+ private int serverPort;
+ private ServerSocket serverSocket;
+ private boolean isStopped;
+ private Connection connection;
+ private int maxConnection = 16;
+
+ /**
+ * Нити, для работы с отдельным клиентом
+ */
+ private List clientThreads;
+
+ private DataStore dataStore;
+
+ /**
+ * Все сессии клиентов
+ */
+ private SessionManager sessionManager;
+
+
+ public MultiThreadServer() {
+ try {
+ Container container = new Container("C:\\Users\\Дмитрий\\Documents\\technotrack\\java\\messenger\\config.xml");
+ WebConnection portAndHost = (WebConnection)container.getByClass("arhangel.dim.container.beans.WebConnection");
+ this.serverPort = portAndHost.getPort();
+ isStopped = false;
+ clientThreads = new ArrayList<>();
+ DataBaseOrganizer.reorganizeDataBase(null);
+ connection = DriverManager.getConnection("jdbc:postgresql://178.62.140.149:5432/Kud8",
+ "trackuser", "trackuser");
+ dataStore = new DataStore(new DataBaseUserStore(connection), new DataBaseChatStore(connection), connection);
+ sessionManager = new SessionManager();
+ } catch (Exception e) {
+ System.err.println("Server: exception caught " + e.toString());
+ }
+ }
+
+ @Override
+ public void run() {
+ try {
+ serverSocket = new ServerSocket(serverPort);
+ while (!isStopped()) {
+ if (clientThreads.size() >= maxConnection) {
+ System.err.println("Error: too much connections");
+ return;
+ }
+ Socket clientSocket = serverSocket.accept();
+ System.out.println("Client connected.");
+ DataInputStream in = new DataInputStream(clientSocket.getInputStream());
+ DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream());
+ Thread thread = new Thread(new CommandHandler(in, out, dataStore, sessionManager));
+ clientThreads.add(thread);
+ thread.start();
+ }
+ } catch (SocketException e) {
+ if (!e.getMessage().equals("socket closed")) {
+ System.err.println("Server: exception caught: " + e.toString());
+ }
+ } catch (Exception e) {
+ System.err.println("Server: exception caught: " + e.toString());
+ } finally {
+ close();
+ }
+ }
+
+ public synchronized boolean isStopped() {
+ return isStopped;
+ }
+
+ private synchronized void stop() {
+ isStopped = true;
+ }
+
+ @Override
+ public void close() {
+ stop();
+ try {
+ serverSocket.close();
+ dataStore.close();
+ connection.close();
+ for (Thread it : clientThreads) {
+ it.join();
+ }
+ } catch (Exception e) {
+ System.err.println("Server: error in closing: " + e.toString());
+ }
+ }
+}
diff --git a/src/main/java/arhangel/dim/server/Server.java b/src/main/java/arhangel/dim/server/Server.java
deleted file mode 100644
index 92452b8..0000000
--- a/src/main/java/arhangel/dim/server/Server.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package arhangel.dim.server;
-
-import arhangel.dim.core.net.Protocol;
-
-/**
- * Основной класс для сервера сообщений
- */
-public class Server {
-
- public static final int DEFAULT_MAX_CONNECT = 16;
-
- // Засетить из конфига
- private int port;
- private Protocol protocol;
- private int maxConnection = DEFAULT_MAX_CONNECT;
-
- public void stop() {
- // TODO: закрыть все сетевые подключения, остановить потоки-обработчики, закрыть ресурсы, если есть.
- }
-
-}
diff --git a/src/main/java/arhangel/dim/server/ServerMain.java b/src/main/java/arhangel/dim/server/ServerMain.java
new file mode 100644
index 0000000..ab1d3eb
--- /dev/null
+++ b/src/main/java/arhangel/dim/server/ServerMain.java
@@ -0,0 +1,27 @@
+package arhangel.dim.server;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+public class ServerMain {
+
+ public static void main(String[] args) {
+ try {
+ MultiThreadServer server = new MultiThreadServer();
+ Thread serverThread = new Thread(server);
+ serverThread.start();
+ System.out.println("Server started, type /stop to stop it");
+ BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
+ while (true) {
+ String line = reader.readLine();
+ if (line.equals("/stop")) {
+ server.close();
+ break;
+ }
+ }
+ serverThread.join();
+ } catch (Exception e) {
+ System.err.println("ServerMain: exception caught: " + e.toString());
+ }
+ }
+}
diff --git a/src/test/java/arhangel/dim/container/ContainerTest.java b/src/test/java/arhangel/dim/container/ContainerTest.java
index 3152f67..6f696de 100644
--- a/src/test/java/arhangel/dim/container/ContainerTest.java
+++ b/src/test/java/arhangel/dim/container/ContainerTest.java
@@ -1,4 +1,4 @@
-package arhangel.dim.container;
+/*package arhangel.dim.container;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -9,9 +9,7 @@
import arhangel.dim.container.beans.Engine;
import arhangel.dim.container.beans.Gear;
-/**
- *
- */
+
public class ContainerTest {
private static Container container;
@@ -55,3 +53,4 @@ public void testGetByClass() throws Exception {
Assert.assertEquals(expectedCar, car);
}
}
+*/
\ No newline at end of file
diff --git a/src/test/java/arhangel/dim/core/net/BinaryProtocolTest.java b/src/test/java/arhangel/dim/core/net/BinaryProtocolTest.java
deleted file mode 100644
index 32d0988..0000000
--- a/src/test/java/arhangel/dim/core/net/BinaryProtocolTest.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package arhangel.dim.core.net;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import arhangel.dim.core.messages.Message;
-import arhangel.dim.core.messages.TextMessage;
-import arhangel.dim.core.messages.Type;
-
-/**
- *
- */
-public class BinaryProtocolTest {
-
- @Test
- public void decode() throws Exception {
- Protocol protocol = new StringProtocol();
- TextMessage message = new TextMessage();
- message.setText("Hello");
- message.setSenderId(1L);
- message.setType(Type.MSG_TEXT);
-
- byte[] data = protocol.encode(message);
- Assert.assertTrue(data != null);
-
- Message other = protocol.decode(data);
- Assert.assertEquals(message, other);
-
- }
-}
\ No newline at end of file