diff --git a/homework-g595-manucharyan/Database.db.mv.db b/homework-g595-manucharyan/Database.db.mv.db new file mode 100644 index 000000000..ff488170f Binary files /dev/null and b/homework-g595-manucharyan/Database.db.mv.db differ diff --git a/homework-g595-manucharyan/pom.xml b/homework-g595-manucharyan/pom.xml index 48adf6d01..2776356cf 100644 --- a/homework-g595-manucharyan/pom.xml +++ b/homework-g595-manucharyan/pom.xml @@ -10,8 +10,13 @@ 4.0.0 homework-g595-manucharyan + pom 1.0.0 + + 1.4.2.RELEASE + + ru.mipt.java2016 @@ -19,6 +24,38 @@ 1.0.0 + + net.sourceforge.jeval + jeval + 0.9.4 + + + + org.springframework.boot + spring-boot-starter-web + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-jdbc + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-security + ${spring.boot.version} + + + com.zaxxer + HikariCP + 2.5.1 + + + com.h2database + h2 + 1.4.193 + + ru.mipt.java2016 homework-tests @@ -26,4 +63,4 @@ test - \ No newline at end of file + diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDao.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDao.java new file mode 100644 index 000000000..999ac4ac2 --- /dev/null +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDao.java @@ -0,0 +1,63 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task4; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Repository; + +import java.sql.ResultSet; +import java.sql.SQLException; + +import javax.annotation.PostConstruct; +import javax.sql.DataSource; + + +@Repository +public class BillingDao { + private static final Logger LOG = LoggerFactory.getLogger(BillingDao.class); + + @Autowired + private DataSource dataSource; + + private JdbcTemplate jdbcTemplate; + + @PostConstruct + public void postConstruct() { + jdbcTemplate = new JdbcTemplate(dataSource, false); + initSchema(); + } + + public void initSchema() { + LOG.trace("Initializing schema"); + jdbcTemplate.execute("CREATE SCHEMA IF NOT EXISTS billing"); + jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS billing.users " + + "(username VARCHAR PRIMARY KEY, password VARCHAR, enabled BOOLEAN)"); + try { + jdbcTemplate.update("INSERT INTO billing.users VALUES ('username', 'password', TRUE)"); + } catch (Exception e) { + System.out.print(""); + } + } + + + public BillingUser loadUser(String username) throws EmptyResultDataAccessException { + LOG.trace("Querying for user " + username); + return jdbcTemplate.queryForObject( + "SELECT username, password, enabled FROM billing.users WHERE username = ?", + new Object[]{username}, + new RowMapper() { + @Override + public BillingUser mapRow(ResultSet rs, int rowNum) throws SQLException { + return new BillingUser( + rs.getString("username"), + rs.getString("password"), + rs.getBoolean("enabled") + ); + } + } + ); + } +} diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDatabaseConfiguration.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDatabaseConfiguration.java new file mode 100644 index 000000000..3a0c0704a --- /dev/null +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDatabaseConfiguration.java @@ -0,0 +1,23 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task4; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.sql.DataSource; + +@Configuration +public class BillingDatabaseConfiguration { + @Bean + public DataSource billingDataSource() { + HikariConfig config = new HikariConfig(); + config.setDriverClassName(org.h2.Driver.class.getName()); + config.setJdbcUrl("jdbc:h2:C:\\Users\\op\\Documents\\GitHub\\mipt-java-2016\\" + + "homework-g595-manucharyan\\Database.db"); + config.setUsername(""); + config.setPassword(""); + return new HikariDataSource(config); + } +} diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingUser.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingUser.java new file mode 100644 index 000000000..5c86b9ba0 --- /dev/null +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingUser.java @@ -0,0 +1,69 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task4; + +public class BillingUser { + private final String username; + private final String password; + private final boolean enabled; + + public BillingUser(String username, String password, boolean enabled) { + if (username == null) { + throw new IllegalArgumentException("Null username is not allowed"); + } + if (password == null) { + throw new IllegalArgumentException("Null password is not allowed"); + } + this.username = username; + this.password = password; + this.enabled = enabled; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + public boolean isEnabled() { + return enabled; + } + + @Override + public String toString() { + return "BillingUser{" + + "username='" + username + '\'' + + ", password='" + password + '\'' + + ", enabled=" + enabled + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + BillingUser that = (BillingUser) o; + + if (enabled != that.enabled) { + return false; + } + if (!username.equals(that.username)) { + return false; + } + return password.equals(that.password); + + } + + @Override + public int hashCode() { + int result = username.hashCode(); + result = 31 * result + password.hashCode(); + result = 31 * result + (enabled ? 1 : 0); + return result; + } +} diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/CalculatorController.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/CalculatorController.java new file mode 100644 index 000000000..3df767a7b --- /dev/null +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/CalculatorController.java @@ -0,0 +1,39 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task4; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import ru.mipt.java2016.homework.base.task1.Calculator; +import ru.mipt.java2016.homework.base.task1.ParsingException; + +@RestController +public class CalculatorController { + private static final Logger LOG = LoggerFactory.getLogger(CalculatorController.class); + @Autowired + private Calculator calculator; + + @RequestMapping(path = "/ping", method = RequestMethod.GET, produces = "text/plain") + public String echo() { + return "OK\n"; + } + + @RequestMapping(path = "/", method = RequestMethod.GET, produces = "text/html") + public String main(@RequestParam(required = false) String name) { + if (name == null) { + name = "world"; + } + return "" + + "FediqApp" + + "

Hello, " + name + "!

" + + ""; + } + + @RequestMapping(path = "/eval", method = RequestMethod.POST, consumes = "text/plain", produces = "text/plain") + public String eval(@RequestBody String expression) throws ParsingException { + LOG.debug("Evaluation request: [" + expression + "]"); + double result = calculator.calculate(expression); + LOG.trace("Result: " + result); + return Double.toString(result) + "\n"; + } +} diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java new file mode 100644 index 000000000..3e6d52f75 --- /dev/null +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java @@ -0,0 +1,437 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task4; + +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import java.util.Stack; + +import ru.mipt.java2016.homework.base.task1.Calculator; +import ru.mipt.java2016.homework.base.task1.ParsingException; + +/** + * Пример реализации калькулятора средствами JEval. + * + * @author vanderwardan + * @since 17.12.16 + */ +public class RESTCalc implements Calculator { + + private Stack operations = new Stack<>(); + private Stack stack = new Stack<>(); // contains expression in postfix notation + private int pos = 0; //position of current symbol in expression + + //names of predefined functions and their valencies + private final Map predefinedFunctions = new HashMap<>(); + //values of variables + private Map variables = new HashMap<>(); + + RESTCalc() { + predefinedFunctions.put("sin", 1); + predefinedFunctions.put("cos", 1); + predefinedFunctions.put("tg", 1); + predefinedFunctions.put("sqrt", 1); + predefinedFunctions.put("pow", 2); + predefinedFunctions.put("abs", 1); + predefinedFunctions.put("sign", 1); + predefinedFunctions.put("log", 1); + predefinedFunctions.put("log2", 1); + predefinedFunctions.put("rnd", 0); + predefinedFunctions.put("max", 2); + predefinedFunctions.put("min", 2); + } + + private int getPriority(Symbol s) throws ParsingException { + switch (s) { + case FUNCTION: + return 0; + case OBRACKET: + return 0; + case CBRACKET: + return 0; + case ADD: + return 1; + case SUB: + return 1; + case MUL: + return 2; + case DIV: + return 2; + case UNOADD: + return 3; + case UNOSUB: + return 3; + default: + freeResource(); + throw new ParsingException("wrong"); + } + } + + private static SymbolType getTokenType(Token t) { + switch (t.getSymbol()) { + case NUMBER: + return SymbolType.NUMBER; + case ADD: + return SymbolType.OPERATOR; + case UNOADD: + return SymbolType.OPERATOR; + case SUB: + return SymbolType.OPERATOR; + case UNOSUB: + return SymbolType.OPERATOR; + case MUL: + return SymbolType.OPERATOR; + case DIV: + return SymbolType.OPERATOR; + case OBRACKET: + return SymbolType.BRACKET; + case CBRACKET: + return SymbolType.BRACKET; + case VARIABLE: + return SymbolType.VARIABLE; + case FUNCTION: + return SymbolType.FUNCTION; + case SPACE: + return SymbolType.SPACE; + default: + return SymbolType.NONE; + } + } + + //is this symbol right-Associativity + private static boolean isRightAssociative(Symbol s) { + //in future, here can be added some right-ass operations =) + switch (s) { + default: + return false; + } + } + + @Override + public double calculate(String expression) throws ParsingException { + try { + if (expression == null) { + throw new ParsingException("wrong"); + } + + //parse expresion and execute it it at the same time + //Really, why should we make reverse polish notation and only than calculate it? + //We can do it both! + while (pos < expression.length()) { + Token t = parseString(expression); //current symbol + + switch (getTokenType(t)) { + case NUMBER: + stack.push(t.getValue()); + break; + case OPERATOR: + pushOperationInStack(t); + break; + case FUNCTION: + operations.push(t); + break; + case BRACKET: + if (t.getSymbol() == Symbol.OBRACKET) { //open bracket + operations.push(t); + } else if (t.getSymbol() == Symbol.CBRACKET) { //close bracket + Token tmp = operations.pop(); + while (!operations.isEmpty() && tmp.getSymbol() != Symbol.OBRACKET || + tmp.getSymbol() == Symbol.FUNCTION) { + calculateOperation(tmp); + if (tmp.getSymbol() == Symbol.FUNCTION) { + break; + } + tmp = operations.pop(); + } + + if (tmp.getSymbol() != Symbol.OBRACKET && tmp.getSymbol() != Symbol.FUNCTION) { + throw new ParsingException("wrong"); + } + } + + break; + case VARIABLE: + if (!variables.containsKey(t.getName())) { + throw new ParsingException("no such variable"); + } + stack.push(variables.get(t.getName())); + break; + case SPACE: + break; + default: + break; + } + + pos++; + } + + //if we parse all expression, and stack isn't empty + while (stack.size() != 1 || operations.size() > 0) { + if (operations.isEmpty()) { + throw new ParsingException("wrong"); + } else { + Token t = operations.pop(); + calculateOperation(t); + } + } + + return stack.pop(); + } finally { + freeResource(); + } + } + + private double getNumber(String expression) throws ParsingException { + char c = expression.charAt(pos); + if (!Character.isDigit(c)) { + freeResource(); + throw new ParsingException("wrong"); + } + + double res = 0.0; + + //find integer part of number + while (Character.isDigit(c)) { + res *= 10; + res += c - '0'; + if (pos == expression.length() - 1) { + break; + } + c = expression.charAt(++pos); + } + + //find fractional part of number + if (c == '.') { + double pow = 0.1; + if (pos >= expression.length() - 1) { + freeResource(); + throw new ParsingException("wrong"); + } + + c = expression.charAt(++pos); + while (Character.isDigit(c)) { + res += (c - '0') * pow; + pow *= 0.1; + if (pos == expression.length() - 1) { + break; + } + c = expression.charAt(++pos); + } + } + + //correct pos + if (!Character.isDigit(c)) { + pos--; + } + + return res; + } + + private double calculateFunction(String name, double[] operands) { + assert (predefinedFunctions.containsKey(name)); + switch (name) { + case "sin": + return Math.sin(operands[0]); + case "cos": + return Math.cos(operands[0]); + case "tg": + return Math.tan(operands[0]); + case "sqrt": + return Math.sqrt(operands[0]); + case "pow": + return Math.pow(operands[0], operands[1]); + case "abs": + return Math.abs(operands[0]); + case "sign": + return Math.signum(operands[0]); + case "log": + return Math.log(operands[0]); + case "log2": + return Math.log(operands[0]) / Math.log(2); + case "rnd": + return (new Random()).nextDouble(); + case "max": + return Math.max(operands[0], operands[1]); + case "min": + return Math.min(operands[0], operands[1]); + default: + return 0.0; + } + } + + //return name of variable or function(in this case, without open bracket) + private String getName(String expression) throws ParsingException { + int oldpos = pos; + String name = ""; + char c = expression.charAt(pos); + + assert (!Character.isDigit(c)); + + while (Character.isLetter(c) || c == '_' || Character.isDigit(c)) { + name += c; + if (pos == expression.length() - 1) { + return name; + } + c = expression.charAt(++pos); + } + pos--; + return name; + } + + //execute operation + private void calculateOperation(Token t) throws ParsingException { + if (stack.size() < t.getValency()) { + freeResource(); + throw new ParsingException("wrong"); + } + + //get all operands + double[] operands = new double[t.getValency()]; + + for (int i = 0; i < t.getValency(); ++i) { + operands[t.getValency() - i - 1] = stack.pop(); + } + + //calculate operation + switch (t.getSymbol()) { + case ADD: + stack.push(operands[0] + operands[1]); + break; + case UNOADD: + stack.push(operands[0]); + break; + case SUB: + stack.push(operands[0] - operands[1]); + break; + case UNOSUB: + stack.push(-operands[0]); + break; + case MUL: + stack.push(operands[0] * operands[1]); + break; + case DIV: + stack.push(operands[0] / operands[1]); + break; + case FUNCTION: + stack.push(calculateFunction(t.getName(), operands)); + break; + default: + freeResource(); + throw new ParsingException("wrong"); + } + } + + private Token parseString(String expression) throws ParsingException { + char c = expression.charAt(pos); + if (Character.isDigit(c)) { + return new Token(Symbol.NUMBER, getNumber(expression)); + } + if (c == '+' || c == '-') { + char oldc = c; + int oldpos = pos; + boolean uno = true; + + //try to understand is operation uno or not + if (pos > 0) { + c = expression.charAt(--pos); + while (c == ' ' || c == '\n' || c == '\t') { + if (pos > 0) { + c = expression.charAt(--pos); + } else { + break; + } + } + if (c == ')' || c >= '0' && c <= '9') { + uno = false; + } + } + + //return answer + pos = oldpos; + if (uno) { + if (oldc == '+') { + return new Token(Symbol.UNOADD); + } else { + return new Token(Symbol.UNOSUB); + } + } else { + if (oldc == '+') { + return new Token(Symbol.ADD); + } else { + return new Token(Symbol.SUB); + } + } + } + if (c == '*') { + return new Token(Symbol.MUL); + } + if (c == '/') { + return new Token(Symbol.DIV); + } + if (c == '(') { + return new Token(Symbol.OBRACKET); + } + if (c == ')') { + return new Token(Symbol.CBRACKET); + } + if (c == '_' || Character.isLetter(c)) { + String name = getName(expression); + if (pos < expression.length() - 1 && expression.charAt(++pos) == '(') { + if (!predefinedFunctions.containsKey(name)) { + throw new ParsingException("no such a function"); + } + return new Token(Symbol.FUNCTION, name, predefinedFunctions.get(name)); + } else { + if (!variables.containsKey(name)) { + throw new ParsingException("no such a variable"); + } + pos--; + return new Token(Symbol.VARIABLE, name, predefinedFunctions.get(name)); + } + } + if (c == ' ' || c == '\n' || c == '\t' || c == ',') { + return new Token(Symbol.SPACE); + } + + //if nothing of that + freeResource(); + throw new ParsingException("wrong"); + } + + //push a single operation in operation stack ("operations") + private void pushOperationInStack(Token t) throws ParsingException { + if (operations.isEmpty()) { + operations.push(t); + } else { + Token tmp = operations.lastElement(); + + //while it's necessary, pop operation and execute it + while ((getPriority(t.getSymbol()) < getPriority(tmp.getSymbol())) && isRightAssociative(t.getSymbol()) || + (getPriority(t.getSymbol()) <= getPriority(tmp.getSymbol())) && !isRightAssociative(t.getSymbol())) { + + operations.pop(); + calculateOperation(tmp); + + if (operations.isEmpty()) { + break; + } else { + tmp = operations.lastElement(); + } + } + + operations.push(t); + } + } + + private void freeResource() { + stack.clear(); + operations.clear(); + + } + + public enum Symbol { + NUMBER, ADD, UNOADD, SUB, UNOSUB, MUL, DIV, OBRACKET, + CBRACKET, VARIABLE, FUNCTION, SPACE, NONE + } + + public enum SymbolType { OPERATOR, NUMBER, BRACKET, SPACE, VARIABLE, FUNCTION, NONE } +} diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/SecurityServiceConfiguration.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/SecurityServiceConfiguration.java new file mode 100644 index 000000000..f0a72ebbe --- /dev/null +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/SecurityServiceConfiguration.java @@ -0,0 +1,56 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task4; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UsernameNotFoundException; + +import java.util.Collections; + +@Configuration +@EnableWebSecurity +public class SecurityServiceConfiguration extends WebSecurityConfigurerAdapter { + private static final Logger LOG = LoggerFactory.getLogger(SecurityServiceConfiguration.class); + + @Autowired + private BillingDao billingDao; + + @Override + protected void configure(HttpSecurity http) throws Exception { + LOG.info("Configuring security"); + http + .httpBasic().realmName("Calculator").and() + .formLogin().disable() + .logout().disable() + .csrf().disable() + .authorizeRequests() + .antMatchers("/eval/**").authenticated() + .anyRequest().permitAll(); + } + + @Autowired + public void registerGlobalAuthentication(AuthenticationManagerBuilder auth) throws Exception { + LOG.info("Register" + + "ing global user details service"); + auth.userDetailsService(username -> { + try { + BillingUser user = billingDao.loadUser(username); + return new User( + user.getUsername(), + user.getPassword(), + Collections.singletonList(() -> "AUTH") + ); + } catch (EmptyResultDataAccessException e) { + LOG.warn("No such user: " + username); + throw new UsernameNotFoundException(username); + } + }); + } +} diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/Token.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/Token.java new file mode 100644 index 000000000..b2fe6ee0d --- /dev/null +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/Token.java @@ -0,0 +1,64 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task4; + +/** + * Created by op on 17.12.2016. + */ +public class Token { + + public Token(RESTCalc.Symbol symbol) { + this.symbol = symbol; + valency = getValencyForOperator(symbol); + } + + public Token(RESTCalc.Symbol symbol, double value) { + this(symbol); + this.value = value; + } + + public Token(RESTCalc.Symbol symbol, String name, int valency) { + this(symbol); + this.name = name; + this.valency = valency; + } + + private double value; // for numbers + private String name; // for functions and variables + private int valency = 0; // for functions + private RESTCalc.Symbol symbol = RESTCalc.Symbol.NONE; + + private int getValencyForOperator(RESTCalc.Symbol s) { + switch (s) { + case ADD: + return 2; + case UNOADD: + return 1; + case SUB: + return 2; + case UNOSUB: + return 1; + case MUL: + return 2; + case DIV: + return 2; + default: + return 0; + } + } + + //get functions + public double getValue() { + return value; + } + + public String getName() { + return name; + } + + public int getValency() { + return valency; + } + + public RESTCalc.Symbol getSymbol() { + return symbol; + } +} diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/VardanApplication.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/VardanApplication.java new file mode 100644 index 000000000..d028150cb --- /dev/null +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/VardanApplication.java @@ -0,0 +1,41 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task4; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.Banner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import ru.mipt.java2016.homework.base.task1.Calculator; + +/**3 + * curl http://localhost:9001/eval \ + * -X POST \ + * -H "Content-Type: text/plain" \ + * -H "Authorization: Basic $(echo -n "username:password" | base64)" \ + * --data-raw "44*3+2" + */ +@EnableAutoConfiguration +@Configuration +@ComponentScan(basePackageClasses = VardanApplication.class) +public class VardanApplication { + + @Bean + public Calculator calculator() { + return new RESTCalc(); + } + + @Bean + public EmbeddedServletContainerCustomizer customizer( + @Value("${ru.mipt.java2016.homework.g595.manucharyan.task4.httpPort:9001}") int port) { + return container -> container.setPort(port); + } + + public static void main(String[] args) { + SpringApplication application = new SpringApplication(VardanApplication.class); + application.setBannerMode(Banner.Mode.OFF); + application.run(args); + } +} diff --git a/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalcTest.java b/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalcTest.java new file mode 100644 index 000000000..fb4c26500 --- /dev/null +++ b/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalcTest.java @@ -0,0 +1,15 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task4; + +import ru.mipt.java2016.homework.base.task1.Calculator; +import ru.mipt.java2016.homework.tests.task1.AbstractCalculatorTest; + +/** + * @author vanderwardan + * @since 19.12.16 + */ +public class RESTCalcTest extends AbstractCalculatorTest { + + protected Calculator calc() { + return new RESTCalc(); + } +}