Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Поправил домашнее задание согласно замечаниям #3

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
45 changes: 24 additions & 21 deletions src/main/java/ru/hh/school/stdlib/Launcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,31 @@

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Launcher {
public static void main(String[] args) throws IOException {
String host;
int port;
try {
if (args.length == 0) {
host = "127.0.0.1";
port = 9129;
} else if (args.length == 3) {
host = args[1];
port = Integer.parseInt(args[2]);
} else {
throw new IllegalArgumentException();
}
} catch (Exception e) {
System.err.printf("Usage: %s [host port]%n", args[0]);
System.exit(1);
return; // попробуйте закомментировать этот return
}
InetSocketAddress addr = InetSocketAddress.createUnresolved(host, port);
public static void main(String[] args) throws IOException {
String host;
int port;
try {
if (args.length == 0) {
host = "127.0.0.1";
port = 9129;
} else if (args.length == 3) {
host = args[1];
port = Integer.parseInt(args[2]);
} else {
throw new IllegalArgumentException();
}
} catch (Exception e) {
System.err.printf("Usage: %s [host port]%n", args[0]);
System.exit(1);
return;
}

new Server(addr).run();
}
InetSocketAddress addr = InetSocketAddress.createUnresolved(host, port);
ExecutorService exec = Executors.newSingleThreadExecutor();
exec.execute(new Server(addr));
}
}
4 changes: 4 additions & 0 deletions src/main/java/ru/hh/school/stdlib/RecursiveException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package ru.hh.school.stdlib;

public class RecursiveException extends Exception {
}
58 changes: 47 additions & 11 deletions src/main/java/ru/hh/school/stdlib/Server.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,53 @@

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Server {
public Server(InetSocketAddress addr) {
throw new UnsupportedOperationException();
}
public class Server implements Runnable {
private int serverPort = 4444;
private ServerSocket serverSocket = null;
private Substitutor3000 substitutor;
private int sleepTime = 0;

public void run() throws IOException {
throw new UnsupportedOperationException();
}
public Server(InetSocketAddress addr) {
this.serverPort = addr.getPort();
substitutor = new Substitutor3000();
}

public int getPort() {
throw new UnsupportedOperationException();
}
}
public void run() {
openServerSocket();
ExecutorService exec = Executors.newCachedThreadPool();
while(true){
Socket clientSocket;
try {
clientSocket = this.serverSocket.accept();
} catch (IOException e) {
throw new RuntimeException("Error accepting client connection", e);
}
exec.execute(new ServerThread(clientSocket, substitutor, this));
}
}

public int getPort() {
return serverPort;
}

private void openServerSocket() {
try {
this.serverSocket = new ServerSocket(this.serverPort);
} catch (IOException e) {
throw new RuntimeException("Cannot open port 8080", e);
}
}

public synchronized int getSleepTime() {
return sleepTime;
}

public synchronized void setSleepTime(int sleepTime) {
this.sleepTime = sleepTime;
}
}
94 changes: 94 additions & 0 deletions src/main/java/ru/hh/school/stdlib/ServerThread.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package ru.hh.school.stdlib;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.concurrent.TimeUnit;

public class ServerThread implements Runnable{
private final static String SUCCESS_REQUEST = "OK\nconnection closed";
private final static String WRONG_REQUEST = "ERROR\nWrong request. Please try again.";
private final static String RECURSIVE_ERROR = "ERROR\nRecursive link detected";

private Socket clientSocket;
private Substitutor3000 substitutor;
private Server server;

public ServerThread(Socket clientSocket, Substitutor3000 substitutor, Server server) {
this.clientSocket = clientSocket;
this.substitutor = substitutor;
this.server = server;
}

public void run() {
try {
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine, outputLine;

while ((inputLine = in.readLine()) != null) {
outputLine = processInput(inputLine);
out.println(outputLine);
if (outputLine.equals("EXIT"))
break;
}

out.close();
in.close();
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}

private String processInput(String inputLine) {
String[] input = inputLine.split("\\s");

if (input[0].equals("GET")) {
sleep();
String key = input[1];
String value;
try {
value = substitutor.get(key);
} catch (RecursiveException e) {
return RECURSIVE_ERROR;
}
return "VALUE\n" + value;
}
else if (input[0].equals("PUT")) {
sleep();
String key = input[1];
String value = "";
for (int i = 2; i < input.length; i++)
value += input[i];
substitutor.put(key, value);
return SUCCESS_REQUEST;
}
else if (input[0].equals("SET")) {
if (input[1].equals("SLEEP")) {
server.setSleepTime(Integer.parseInt(input[2]));
return SUCCESS_REQUEST;
}
else
return WRONG_REQUEST;
}
else if (input[0].equals("EXIT")) {
return "EXIT";
}
else {
return WRONG_REQUEST;
}
}

private void sleep() {
if (server.getSleepTime() != 0) {
try {
TimeUnit.MILLISECONDS.sleep(server.getSleepTime());
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
}
40 changes: 34 additions & 6 deletions src/main/java/ru/hh/school/stdlib/Substitutor3000.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,39 @@
package ru.hh.school.stdlib;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Substitutor3000 {
public void put(String key, String value) {
throw new UnsupportedOperationException();
}
private Map<String,String> map = Collections.synchronizedMap(new HashMap<String, String>());
private ArrayList<String> keys = new ArrayList<String>();

public synchronized void put(String key, String value) {
map.put(key, value);
}

public synchronized String get(String key) throws RecursiveException {
String regex = "\\$\\{(\\w+)\\}";
String value = map.get(key);
if (value == null)
return "";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(value);

if (keys.contains(value))
throw new RecursiveException();
keys.add(value);
while (m.find()) {
value = value.replaceFirst(regex, get(m.group(1)));
m = p.matcher(value);
}
keys.remove(value);
if (!value.contains(" "))
value += " ";

public String get(String key) {
throw new UnsupportedOperationException();
}
return value;
}
}
80 changes: 40 additions & 40 deletions src/test/java/ru/hh/school/stdlib/BaseFunctionalTest.java
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
package ru.hh.school.stdlib;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;

public class BaseFunctionalTest {
private static Server server;

protected BaseFunctionalTest() {
synchronized (BaseFunctionalTest.class) {
try {
if (server == null) {
server = new Server(new InetSocketAddress("127.0.0.1", 0));
new Thread(new Runnable() {
public void run() {
try {
server.run();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}).start();
Thread.sleep(100);
System.out.printf("Server started on port %d%n", server.getPort());
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

protected Socket connect() {
try {
return new Socket("127.0.0.1", server.getPort());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
package ru.hh.school.stdlib;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
public class BaseFunctionalTest {
private static Server server;
protected BaseFunctionalTest() {
synchronized (BaseFunctionalTest.class) {
try {
if (server == null) {
server = new Server(new InetSocketAddress("127.0.0.1", 4444));
new Thread(new Runnable() {
public void run() {
//try {
server.run();
//} catch (IOException e) {
//throw new RuntimeException(e);
// }
}
}).start();
Thread.sleep(100);
System.out.printf("Server started on port %d%n", server.getPort());
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
protected Socket connect() {
try {
return new Socket("127.0.0.1", server.getPort());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
38 changes: 38 additions & 0 deletions src/test/java/ru/hh/school/stdlib/MultiConnection.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package ru.hh.school.stdlib;

import org.junit.Assert;
import org.junit.Test;

import java.io.*;
import java.net.Socket;

public class MultiConnection extends BaseFunctionalTest {

@Test
public void testMultiConnection() throws IOException {
long timePeriod = 2000;

Socket s1 = connect();
Socket s2 = connect();

Writer out1 = new PrintWriter(s1.getOutputStream());
BufferedReader in1 = new BufferedReader(new InputStreamReader(s1.getInputStream()));
Writer out2 = new PrintWriter(s2.getOutputStream());
BufferedReader in2 = new BufferedReader(new InputStreamReader(s2.getInputStream()));

out1.append("SET SLEEP " + timePeriod + "\n").flush();
Assert.assertEquals("OK", in1.readLine());
Assert.assertEquals("connection closed", in1.readLine());
long start = System.currentTimeMillis();
out1.append("GET k1\n").flush();
out2.append("GET k1\n").flush();
Assert.assertEquals("VALUE", in1.readLine());
Assert.assertEquals("", in1.readLine());
Assert.assertEquals("VALUE", in2.readLine());
Assert.assertEquals("", in2.readLine());
long end = System.currentTimeMillis();

Assert.assertTrue((end - start) < (timePeriod * 2));
System.out.println(end - start);
}
}
Loading