From 95749bdaed96d3ab60ad69dbb2408ec53003dbc2 Mon Sep 17 00:00:00 2001 From: shevkunov Date: Sat, 10 Dec 2016 20:29:20 +0300 Subject: [PATCH 1/8] =?UTF-8?q?=D0=9D=D0=B0=D1=87=D0=B0=D1=82=D0=BE=20?= =?UTF-8?q?=D0=BA=D1=80=D0=B0=D0=B9=D0=BD=D0=B5=D0=B5=20=D0=B7=D0=B0=D0=B4?= =?UTF-8?q?=D0=B0=D0=BD=D0=B8=D0=B5.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- homework-g594-shevkunov/pom.xml | 30 ++++++++ .../shevkunov/task1/PolishCalculator.java | 2 +- .../g594/shevkunov/task4/BillingDao.java | 59 ++++++++++++++++ .../task4/BillingDatabaseConfiguration.java | 26 +++++++ .../g594/shevkunov/task4/BillingUser.java | 69 +++++++++++++++++++ .../shevkunov/task4/CalculatorController.java | 51 ++++++++++++++ .../shevkunov/task4/FediqApplication.java | 42 +++++++++++ .../task4/SecurityServiceConfiguration.java | 55 +++++++++++++++ 8 files changed, 333 insertions(+), 1 deletion(-) create mode 100644 homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java create mode 100644 homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDatabaseConfiguration.java create mode 100644 homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingUser.java create mode 100644 homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java create mode 100644 homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FediqApplication.java create mode 100644 homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/SecurityServiceConfiguration.java diff --git a/homework-g594-shevkunov/pom.xml b/homework-g594-shevkunov/pom.xml index cf6cbf5d1..c62bb52f4 100644 --- a/homework-g594-shevkunov/pom.xml +++ b/homework-g594-shevkunov/pom.xml @@ -12,6 +12,10 @@ homework-g594-shevkunov 1.0.0 + + 1.4.2.RELEASE + + ru.mipt.java2016 @@ -29,6 +33,32 @@ guava 20.0 + + 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 + + \ No newline at end of file diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task1/PolishCalculator.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task1/PolishCalculator.java index 6778fdebc..65272ee6b 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task1/PolishCalculator.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task1/PolishCalculator.java @@ -11,7 +11,7 @@ * Evaluates a value from expressing * Created by shevkunov on 04.10.16. */ -class PolishCalculator implements Calculator { +public class PolishCalculator implements Calculator { private Stack valStack = new Stack<>(); private Stack operStack = new Stack<>(); private StringBuilder buffer = new StringBuilder(); diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java new file mode 100644 index 000000000..d39d4e8da --- /dev/null +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java @@ -0,0 +1,59 @@ +package ru.mipt.java2016.homework.g594.shevkunov.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 javax.annotation.PostConstruct; +import javax.sql.DataSource; +import java.sql.ResultSet; +import java.sql.SQLException; + +@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)"); + jdbcTemplate.execute("DELETE FROM billing.users WHERE username = 'username'"); + jdbcTemplate.update("INSERT INTO billing.users VALUES ('username', 'password', TRUE) "); + } + + + 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-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDatabaseConfiguration.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDatabaseConfiguration.java new file mode 100644 index 000000000..e3e2cd883 --- /dev/null +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDatabaseConfiguration.java @@ -0,0 +1,26 @@ +package ru.mipt.java2016.homework.g594.shevkunov.task4; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.sql.DataSource; + +@Configuration +public class BillingDatabaseConfiguration { + @Bean + public DataSource billingDataSource( + @Value("${ru.mipt.java2016.homework.g000.lavrentyev.task4.jdbcUrl:jdbc:h2:/tmp/task4/base}") String jdbcUrl, + @Value("${ru.mipt.java2016.homework.g000.lavrentyev.task4.username:}") String username, + @Value("${ru.mipt.java2016.homework.g000.lavrentyev.task4.password:}") String password + ) { + HikariConfig config = new HikariConfig(); + config.setDriverClassName(org.h2.Driver.class.getName()); + config.setJdbcUrl(jdbcUrl); + config.setUsername(username); + config.setPassword(password); + return new HikariDataSource(config); + } +} diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingUser.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingUser.java new file mode 100644 index 000000000..b85caba6b --- /dev/null +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingUser.java @@ -0,0 +1,69 @@ +package ru.mipt.java2016.homework.g594.shevkunov.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-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java new file mode 100644 index 000000000..178dd30e5 --- /dev/null +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java @@ -0,0 +1,51 @@ +package ru.mipt.java2016.homework.g594.shevkunov.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 evalPost(@RequestBody String expression) throws ParsingException { + LOG.debug("Evaluation request: [" + expression + "]"); + String result; + try { + double dResult = calculator.calculate(expression); + result = Double.toString(dResult) + "\n"; + } catch (Throwable e) { + result = "InvalidExpression.\n"; + } + + LOG.trace("Result: " + result); + return result; + } + + @RequestMapping(path = "/eval", method = RequestMethod.GET, produces = "text/html") + public String evalGet() throws ParsingException { + return "You should use POST method.\n"; + } +} diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FediqApplication.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FediqApplication.java new file mode 100644 index 000000000..3620eec25 --- /dev/null +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FediqApplication.java @@ -0,0 +1,42 @@ +package ru.mipt.java2016.homework.g594.shevkunov.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; +import ru.mipt.java2016.homework.g594.shevkunov.task1.PolishCalculator; + +/** + * 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 = FediqApplication.class) +public class FediqApplication { + + @Bean + public Calculator calculator() { + return new PolishCalculator(); + } + + @Bean + public EmbeddedServletContainerCustomizer customizer( + @Value("${ru.mipt.java2016.homework.g000.lavrentyev.task4.httpPort:9001}") int port) { + return container -> container.setPort(port); + } + + public static void main(String[] args) { + SpringApplication application = new SpringApplication(FediqApplication.class); + application.setBannerMode(Banner.Mode.OFF); + application.run(args); + } +} diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/SecurityServiceConfiguration.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/SecurityServiceConfiguration.java new file mode 100644 index 000000000..a29cedd0d --- /dev/null +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/SecurityServiceConfiguration.java @@ -0,0 +1,55 @@ +package ru.mipt.java2016.homework.g594.shevkunov.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("Registering 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); + } + }); + } +} From 5cce3d1f15dcf8614b24bd445295efd1be848a70 Mon Sep 17 00:00:00 2001 From: shevkunov Date: Fri, 16 Dec 2016 18:37:58 +0300 Subject: [PATCH 2/8] =?UTF-8?q?=D0=A1=D0=B4=D0=B5=D0=BB=D0=B0=D0=BD=D0=BE?= =?UTF-8?q?=20=D0=B2=D1=8B=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=20=D0=B7=D0=B0=D0=BF=D1=80=D0=BE=D1=81=D0=BE=D0=B2=20=D0=BF?= =?UTF-8?q?=D0=BE=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BC=D0=B5=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D0=BC=20=D0=B2=20=D0=91=D0=94.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shevkunov/task4/AdvancedCalculator.java | 23 + .../g594/shevkunov/task4/BillingDao.java | 49 ++ .../shevkunov/task4/CalculatorController.java | 101 +++++ .../shevkunov/task4/FediqApplication.java | 3 +- .../shevkunov/task4/PolishCalculator.java | 422 ++++++++++++++++++ 5 files changed, 596 insertions(+), 2 deletions(-) create mode 100644 homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/AdvancedCalculator.java create mode 100644 homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/PolishCalculator.java diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/AdvancedCalculator.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/AdvancedCalculator.java new file mode 100644 index 000000000..0a67249ff --- /dev/null +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/AdvancedCalculator.java @@ -0,0 +1,23 @@ +package ru.mipt.java2016.homework.g594.shevkunov.task4; + +import org.springframework.beans.factory.annotation.Autowired; +import ru.mipt.java2016.homework.base.task1.Calculator; +import ru.mipt.java2016.homework.base.task1.ParsingException; +import ru.mipt.java2016.homework.g594.shevkunov.task1.PolishCalculator; + +/** + * Evaluates a value from expressing + * Created by shevkunov on 04.10.16. + */ +public class AdvancedCalculator implements Calculator { + + @Autowired + private BillingDao billingDao; + + private PolishCalculator simpleCalculator = + new PolishCalculator(); + @Override + public double calculate(String expression) throws ParsingException { + return simpleCalculator.calculate(expression); + } +} diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java index d39d4e8da..30254e1dc 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java @@ -12,6 +12,9 @@ import javax.sql.DataSource; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; @Repository public class BillingDao { @@ -34,6 +37,11 @@ public void initSchema() { jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS billing.users " + "(username VARCHAR PRIMARY KEY, password VARCHAR, enabled BOOLEAN)"); + + jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS billing.vars " + + "(variable VARCHAR PRIMARY KEY, username VARCHAR," + //TODO FOREIGN KEY + " value VARCHAR)"); + jdbcTemplate.execute("DELETE FROM billing.users WHERE username = 'username'"); jdbcTemplate.update("INSERT INTO billing.users VALUES ('username', 'password', TRUE) "); } @@ -56,4 +64,45 @@ public BillingUser mapRow(ResultSet rs, int rowNum) throws SQLException { } ); } + + public void setVariable(String username, String variable, String value) { + delVariable(username, variable); + String querry = "INSERT INTO billing.vars VALUES ('" + variable + "','" + username + "','" + value + "')"; + jdbcTemplate.execute(querry); + } + + public String getVariable(String username, String variable) { + LOG.trace("Getting variable " + variable + " for user " + username); + String querry = "SELECT value FROM billing.vars WHERE username = '" + + username + "' AND variable = '" + variable + "'"; + return jdbcTemplate.queryForObject( + querry, + new RowMapper() { + @Override + public String mapRow(ResultSet rs, int rowNum) throws SQLException { + return rs.getString("value"); + } + } + ); + } + + public List getAllVariables(String username) { + LOG.trace("Getting all variables for user " + username); + String querry = "SELECT * FROM billing.vars"; // TODO make faster + + List vars = new ArrayList(); + + List> rows = jdbcTemplate.queryForList(querry); + + for (Map row : rows) { + vars.add((String)row.get("variable")); + } + return vars; + } + + public void delVariable(String username, String variable) { + LOG.trace("Deletting variable " + variable + " for user " + username); // TODO check valid + String querry = "DELETE FROM billing.vars WHERE username = '" +username + "' AND variable = '" + variable +"'"; + jdbcTemplate.execute(querry); + } } diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java index 178dd30e5..eba28fc20 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java @@ -7,9 +7,16 @@ import ru.mipt.java2016.homework.base.task1.Calculator; import ru.mipt.java2016.homework.base.task1.ParsingException; +import java.util.Iterator; +import java.util.List; + @RestController public class CalculatorController { private static final Logger LOG = LoggerFactory.getLogger(CalculatorController.class); + + @Autowired + private BillingDao billingDao; + @Autowired private Calculator calculator; @@ -48,4 +55,98 @@ public String evalPost(@RequestBody String expression) throws ParsingException { public String evalGet() throws ParsingException { return "You should use POST method.\n"; } + + /*** Variables functions + * GET /variable/${variableName} + * + * PUT /variable/${variableName} + * variable value + * + * DELETE /variable/${variableName} + * + * GET /variable/ + * + * TODO Remove this*/ + + @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.GET, produces = "text/html") + public String varGet(@PathVariable String variableName) throws ParsingException { + return billingDao.getVariable("username", variableName) + "\n"; + } + + @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.PUT, produces = "text/html") + public String varPut(@PathVariable String variableName, @RequestBody String value) throws ParsingException { + String result = "OK\n"; + try { + billingDao.setVariable("username", variableName, value); + } catch (Exception e) { + result = "Server Internal Error.\n"; + } + return result; + } + + @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.DELETE, produces = "text/html") + public String varDel(@PathVariable String variableName) throws ParsingException { + String result = "OK\n"; + try { + billingDao.delVariable("username", variableName); + } catch (Exception e) { + result = "Server Internal Error.\n"; + } + return result; + } + + @RequestMapping(path = "/variable/", method = RequestMethod.GET, produces = "text/html") + public String allVarGet() throws ParsingException { + List allVar = billingDao.getAllVariables("username"); // TODO Normal user + String all = "'"; + for (Iterator i = allVar.iterator(); i.hasNext(); ) { + all += i.next(); + if (i.hasNext()) { + all += "', '"; + } else { + all += "'"; + } + } + + return all + "\n"; + } + + /*** Function functions + * GET /function/${functionName} + * + * PUT /function/${functionName}?args=${argumentsList} + * function expression + * + * DELETE /function/${functionName} + * + * GET /function/ + * + * TODO Remove this*/ + + @RequestMapping(path = "/function/{functionName}", method = RequestMethod.GET, produces = "text/html") + public String funcGet(@PathVariable String functionName) throws ParsingException { + return "Requested: " + functionName + "\n" + + "This function doesn't implemented yet.\n"; + } + + @RequestMapping(path = "/function/{functionName}", method = RequestMethod.PUT, produces = "text/html") + public String funcPut(@PathVariable String functionName, + @RequestParam(value = "args") List arguments, + @RequestBody String request) throws ParsingException { + return "An attempt to put: " + functionName + "\n" + + "With request = " + request + "\n" + + "This function doesn't implemented yet.\n"; + } + + @RequestMapping(path = "/function/{functionName}", method = RequestMethod.DELETE, produces = "text/html") + public String funcDel(@PathVariable String functionName) throws ParsingException { + return "An attempt to delete: " + functionName + "\n" + + "This function doesn't implemented yet.\n"; + } + + @RequestMapping(path = "/function/", method = RequestMethod.GET, produces = "text/html") + public String allFuncGet() throws ParsingException { + return "Requested all functions \n" + + "This function doesn't implemented yet.\n"; + } } diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FediqApplication.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FediqApplication.java index 3620eec25..d65bb4f1b 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FediqApplication.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FediqApplication.java @@ -9,7 +9,6 @@ import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import ru.mipt.java2016.homework.base.task1.Calculator; -import ru.mipt.java2016.homework.g594.shevkunov.task1.PolishCalculator; /** * curl http://localhost:9001/eval \ @@ -25,7 +24,7 @@ public class FediqApplication { @Bean public Calculator calculator() { - return new PolishCalculator(); + return new AdvancedCalculator(); } @Bean diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/PolishCalculator.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/PolishCalculator.java new file mode 100644 index 000000000..d793c7205 --- /dev/null +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/PolishCalculator.java @@ -0,0 +1,422 @@ +package ru.mipt.java2016.homework.g594.shevkunov.task4; + +import ru.mipt.java2016.homework.base.task1.Calculator; +import ru.mipt.java2016.homework.base.task1.ParsingException; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Stack; + +/** + * Evaluates a value from expressing + * Created by shevkunov on 04.10.16. + */ +public class PolishCalculator implements Calculator { + private Stack valStack = new Stack<>(); + private Stack operStack = new Stack<>(); + private StringBuilder buffer = new StringBuilder(); + private ParserState state = ParserState.NONE; + private boolean unary = true; + + public double calculate(String expression) throws ParsingException { + if (expression == null) { + throw new ParsingException("Null expression."); + } else { + if (expression.length() == 0) { + throw new ParsingException("I think, the result are 42."); + } else { + return parse(expression); + } + } + } + + private void proceedOperation(Operation eval) throws ParsingException { + if (eval.isBracket()) { + throw new ParsingException("Incorrect expression."); + } + double[] args = new double[eval.valence()]; + for (int argIndex = args.length - 1; argIndex >= 0; --argIndex) { + if (!valStack.isEmpty()) { + args[argIndex] = valStack.pop(); + } else { + throw new ParsingException("Incorrect expression."); + } + } + valStack.push(eval.evaluate(args)); + } + + private void pushOperation(String opString, boolean isUnary) throws ParsingException { + Operation op = + isUnary ? Operation.getOperation("U" + opString) : Operation.getOperation(opString); + if (null != op) { // Yoda style + if (!op.isBracket()) { + while (!operStack.isEmpty() && ( + ((operStack.peek().valence() != 1) && operStack.peek().notWeakerThan(op)) + || (operStack.peek().valence() == 1) && operStack.peek() + .strongerThan(op))) { + proceedOperation(operStack.pop()); + } + operStack.push(op); + } else { + if (op.closeBracket() == null) { + operStack.push(op); + } else { + while (!operStack.isEmpty() && (operStack.peek() != op.closeBracket())) { + proceedOperation(operStack.pop()); + } + if (operStack.isEmpty()) { + throw new ParsingException("Incorrect expression."); + } else { + operStack.pop(); + } + } + } + } else { + throw new ParsingException("Unknown operation : " + opString); + } + } + + private void pushBuffer() throws ParsingException { + switch (state) { + case OPER: + pushOperation(buffer.toString(), unary); + unary = true; + break; + case VAL: + try { + valStack.push(Double.parseDouble(buffer.toString())); + } catch (NumberFormatException e) { + throw new ParsingException("Bad number."); + } + unary = false; + break; + default: + // do nothing + } + buffer.delete(0, buffer.length()); + } + + private double parse(String expr) throws ParsingException { + unary = true; + state = ParserState.NONE; + for (int i = 0; i < expr.length(); ++i) { + if (Character.isDigit(expr.charAt(i)) || (expr.charAt(i) == '.')) { + if (state != ParserState.VAL) { + pushBuffer(); + state = ParserState.VAL; + } + buffer.append(expr.charAt(i)); + } else { + if (Character.isWhitespace(expr.charAt(i))) { + pushBuffer(); + state = ParserState.NONE; + } else { + if (state != ParserState.OPER) { + pushBuffer(); + state = ParserState.OPER; + } + buffer.append(expr.charAt(i)); + Operation readed = Operation + .getOperation(unary ? "U" + buffer.toString() : buffer.toString()); + if (null != readed) { + if (readed.isBracket()) { + unary = false; + pushBuffer(); + state = ParserState.NONE; + unary = readed.closeBracket() == null; + } else { + if ((!operStack.empty()) && (operStack.peek() == Operation.UNARYPLUS) + && (readed == Operation.UNARYPLUS)) { + throw new ParsingException("I love ++i"); + // I think that ++1 is correct; + // this is ony for testPlusPlus + } + pushBuffer(); + unary = true; + state = ParserState.NONE; + } + } + } + } + } + pushBuffer(); + + while (!operStack.isEmpty()) { + proceedOperation(operStack.pop()); + } + if (valStack.size() != 1) { + throw new ParsingException("Incorrect expression."); + } + return valStack.pop(); + } + + private enum ParserState { + OPER, VAL, NONE + } + + + private enum Operation { + PLUS(0) { + @Override + public double compute(double... args) { + double result = 0.; // neutral element + for (double value : args) { + result += value; + } + return result; + } + }, MINUS(0) { + @Override + public double compute(double... args) { + if (args.length == 1) { + return 0. - args[0]; + } else { + if (args.length > 1) { + double result = args[0]; + for (int i = 1; i < args.length; ++i) { + result -= args[i]; + } + return result; + } else { + return 0.; // neutral element + } + } + } + }, MULTIPLY(1) { + @Override + public double compute(double... args) { + double result = 1.; //neutral elent + for (double value : args) { + result *= value; + } + return result; + } + }, DIVISION(1) { + @Override + public double compute(double... args) { + if (args.length == 1) { + return 1. / args[0]; + } else { + if (args.length > 1) { + double result = args[0]; + for (int i = 1; i < args.length; ++i) { + result /= args[i]; + } + return result; + } else { + return 1.; // neutral element + } + } + } + }, UNARYPLUS(777) { + @Override + public int valence() { + return 1; + } + + @Override + public double compute(double... args) { + return +args[0]; + } + }, UNARYMINUS(777) { + @Override + public int valence() { + return 1; + } + + @Override + public double compute(double... args) { + return -args[0]; + } + }, OPENBRAСKET(-1) { + @Override + public int valence() { + return 0; + } + + @Override + public boolean isBracket() { + return true; + } + + @Override + public double compute(double... args) { + return Double.NaN; + } + }, CLOSEBRAСKET(-1) { + @Override + public int valence() { + return 0; + } + + @Override + public boolean isBracket() { + return true; + } + + @Override + public PolishCalculator.Operation closeBracket() { + return PolishCalculator.Operation.OPENBRAСKET; + } + + @Override + public double compute(double... args) { + return Double.NaN; + } + }, SIN(2) { + @Override + public int valence() { + return 1; + } + + @Override + public double compute(double... args) { + return Math.sin(args[0]); + } + }, COS(2) { + @Override + public int valence() { + return 1; + } + + @Override + public double compute(double... args) { + return Math.cos(args[0]); + } + }, TG(2) { + @Override + public int valence() { + return 1; + } + + @Override + public double compute(double... args) { + return Math.tan(args[0]); + } + }, SQRT(2) { + @Override + public int valence() { + return 1; + } + + @Override + public double compute(double... args) { + return Math.sqrt(args[0]); + } + }, ABS(2) { + @Override + public int valence() { + return 1; + } + + @Override + public double compute(double... args) { + return Math.abs(args[0]); + } + }, SIGN(2) { + @Override + public int valence() { + return 1; + } + + @Override + public double compute(double... args) { + return Math.signum(args[0]); + } + } , LOG2(2) { + @Override + public int valence() { + return 1; + } + + @Override + public double compute(double... args) { + return Math.log(args[0]) / Math.log(2.); + } + }, POW(3) { + @Override + public double compute(double... args) { + return Math.pow(args[0], args[1]); + } + }, LOG(3) { + @Override + public double compute(double... args) { + return Math.log(args[0]) / Math.log(args[1]); + } + }, MAX(3) { + @Override + public double compute(double... args) { + return Math.max(args[0], args[1]); + } + }, MIN(4) { + @Override + public double compute(double... args) { + return Math.min(args[0], args[1]); + } + }; + // TODO RND + + private static final Map STRING_REPRESENTATIONS; + + static { + Map map = new HashMap<>(); + map.put("+", Operation.PLUS); + map.put("-", Operation.MINUS); + map.put("*", Operation.MULTIPLY); + map.put("/", Operation.DIVISION); + map.put("U+", Operation.UNARYPLUS); + map.put("U-", Operation.UNARYMINUS); + map.put("(", Operation.OPENBRAСKET); + map.put(")", Operation.CLOSEBRAСKET); + + map.put("U(", Operation.OPENBRAСKET); + map.put("U)", Operation.CLOSEBRAСKET); + + STRING_REPRESENTATIONS = Collections.unmodifiableMap(map); + } + + private final int order; + + Operation(int order) { + this.order = order; + } + + public static Operation getOperation(String name) { + if (STRING_REPRESENTATIONS.containsKey(name)) { + return STRING_REPRESENTATIONS.get(name); + } else { + return null; + } + } + + protected abstract double compute(double[] args); + + public double evaluate(double... args) throws ParsingException { + if (valence() != args.length) { + throw new ParsingException("Invalid valence."); + } + return compute(args); + } + + public boolean isBracket() { + return false; + } + + public Operation closeBracket() { + return null; // not a (close) bracket + } + + public int valence() { + return 2; // default + } + + public boolean strongerThan(Operation op) { + return this.order > op.order; + } + + public boolean notWeakerThan(Operation op) { + return this.order >= op.order; + } + } +} From 9170533321f82d64b331297e3c9caef780d34ea3 Mon Sep 17 00:00:00 2001 From: shevkunov Date: Fri, 16 Dec 2016 19:28:47 +0300 Subject: [PATCH 3/8] =?UTF-8?q?=D0=A0=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D1=8E?= =?UTF-8?q?=D1=82=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BC=D0=B5=D0=BD=D0=BD=D1=8B?= =?UTF-8?q?=D0=B5.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shevkunov/task4/AdvancedCalculator.java | 23 ----------- .../g594/shevkunov/task4/BillingDao.java | 21 +++++++--- .../shevkunov/task4/CalculatorController.java | 39 ++++++++++++++++++- .../shevkunov/task4/FediqApplication.java | 2 +- 4 files changed, 54 insertions(+), 31 deletions(-) delete mode 100644 homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/AdvancedCalculator.java diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/AdvancedCalculator.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/AdvancedCalculator.java deleted file mode 100644 index 0a67249ff..000000000 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/AdvancedCalculator.java +++ /dev/null @@ -1,23 +0,0 @@ -package ru.mipt.java2016.homework.g594.shevkunov.task4; - -import org.springframework.beans.factory.annotation.Autowired; -import ru.mipt.java2016.homework.base.task1.Calculator; -import ru.mipt.java2016.homework.base.task1.ParsingException; -import ru.mipt.java2016.homework.g594.shevkunov.task1.PolishCalculator; - -/** - * Evaluates a value from expressing - * Created by shevkunov on 04.10.16. - */ -public class AdvancedCalculator implements Calculator { - - @Autowired - private BillingDao billingDao; - - private PolishCalculator simpleCalculator = - new PolishCalculator(); - @Override - public double calculate(String expression) throws ParsingException { - return simpleCalculator.calculate(expression); - } -} diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java index 30254e1dc..28579eae7 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java @@ -12,9 +12,7 @@ import javax.sql.DataSource; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.util.*; @Repository public class BillingDao { @@ -86,9 +84,9 @@ public String mapRow(ResultSet rs, int rowNum) throws SQLException { ); } - public List getAllVariables(String username) { + public List getAllVariableNames(String username) { LOG.trace("Getting all variables for user " + username); - String querry = "SELECT * FROM billing.vars"; // TODO make faster + String querry = "SELECT variable FROM billing.vars"; // TODO make faster List vars = new ArrayList(); @@ -100,6 +98,19 @@ public List getAllVariables(String username) { return vars; } + public Map getAllVariables(String username) { + LOG.trace("Getting all variables for user " + username); + String querry = "SELECT * FROM billing.vars"; // TODO make faster + + Map vars = new HashMap<>(); + + List> rows = jdbcTemplate.queryForList(querry); + for (Map row : rows) { + vars.put((String)row.get("variable"), (String)row.get("value")); + } + return vars; + } + public void delVariable(String username, String variable) { LOG.trace("Deletting variable " + variable + " for user " + username); // TODO check valid String querry = "DELETE FROM billing.vars WHERE username = '" +username + "' AND variable = '" + variable +"'"; diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java index eba28fc20..82d4ecbec 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java @@ -9,6 +9,7 @@ import java.util.Iterator; import java.util.List; +import java.util.Map; @RestController public class CalculatorController { @@ -41,7 +42,7 @@ public String evalPost(@RequestBody String expression) throws ParsingException { LOG.debug("Evaluation request: [" + expression + "]"); String result; try { - double dResult = calculator.calculate(expression); + double dResult = rebuildAndCalculate(expression, billingDao.getAllVariables("username")); // TODO username result = Double.toString(dResult) + "\n"; } catch (Throwable e) { result = "InvalidExpression.\n"; @@ -97,7 +98,7 @@ public String varDel(@PathVariable String variableName) throws ParsingException @RequestMapping(path = "/variable/", method = RequestMethod.GET, produces = "text/html") public String allVarGet() throws ParsingException { - List allVar = billingDao.getAllVariables("username"); // TODO Normal user + List allVar = billingDao.getAllVariableNames("username"); // TODO Normal user String all = "'"; for (Iterator i = allVar.iterator(); i.hasNext(); ) { all += i.next(); @@ -149,4 +150,38 @@ public String allFuncGet() throws ParsingException { return "Requested all functions \n" + "This function doesn't implemented yet.\n"; } + + private boolean isVariableChar(char ch) { + return Character.isAlphabetic(ch) || Character.isDigit(ch) || ch == '_'; + } + + private double rebuildAndCalculate(String expression, Map variables) throws ParsingException { + StringBuilder buffer = new StringBuilder(); + StringBuilder newExpression = new StringBuilder(); + + + for (int i = 0; i < expression.length(); ++i) { + if (isVariableChar(expression.charAt(i))) { + buffer.append(expression.charAt(i)); + } + + if (!isVariableChar(expression.charAt(i)) || (expression.length() == i + 1)) { + String proceed = buffer.toString(); + buffer.delete(0, buffer.length()); + + if (variables.containsKey(proceed)) { + newExpression.append(variables.get(proceed)); + } else { + newExpression.append(proceed); + } + + if (!isVariableChar(expression.charAt(i))) { + newExpression.append(expression.charAt(i)); + } + } + + + } + return calculator.calculate(newExpression.toString()); + } } diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FediqApplication.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FediqApplication.java index d65bb4f1b..fd0eb8fbd 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FediqApplication.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FediqApplication.java @@ -24,7 +24,7 @@ public class FediqApplication { @Bean public Calculator calculator() { - return new AdvancedCalculator(); + return new PolishCalculator(); } @Bean From 4800cbbc679e806733ead72877f620135623eb4e Mon Sep 17 00:00:00 2001 From: shevkunov Date: Fri, 16 Dec 2016 21:01:26 +0300 Subject: [PATCH 4/8] =?UTF-8?q?=D0=A0=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D0=B5?= =?UTF-8?q?=D1=82=20=D0=B0=D0=B2=D1=82=D0=BE=D1=80=D0=B8=D0=B7=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D1=8F.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../g594/shevkunov/task4/BillingDao.java | 8 ++- .../shevkunov/task4/CalculatorController.java | 65 +++++++++---------- .../task4/SecurityServiceConfiguration.java | 2 +- 3 files changed, 35 insertions(+), 40 deletions(-) diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java index 28579eae7..5e4d5192c 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java @@ -41,7 +41,9 @@ public void initSchema() { " value VARCHAR)"); jdbcTemplate.execute("DELETE FROM billing.users WHERE username = 'username'"); + jdbcTemplate.execute("DELETE FROM billing.users WHERE username = 'sudoname'"); jdbcTemplate.update("INSERT INTO billing.users VALUES ('username', 'password', TRUE) "); + jdbcTemplate.update("INSERT INTO billing.users VALUES ('sudoname', 'aptitude', TRUE) "); } @@ -86,7 +88,7 @@ public String mapRow(ResultSet rs, int rowNum) throws SQLException { public List getAllVariableNames(String username) { LOG.trace("Getting all variables for user " + username); - String querry = "SELECT variable FROM billing.vars"; // TODO make faster + String querry = "SELECT variable FROM billing.vars WHERE username = '" + username + "'"; List vars = new ArrayList(); @@ -100,7 +102,7 @@ public List getAllVariableNames(String username) { public Map getAllVariables(String username) { LOG.trace("Getting all variables for user " + username); - String querry = "SELECT * FROM billing.vars"; // TODO make faster + String querry = "SELECT * FROM billing.vars WHERE username = '" + username + "'"; Map vars = new HashMap<>(); @@ -113,7 +115,7 @@ public Map getAllVariables(String username) { public void delVariable(String username, String variable) { LOG.trace("Deletting variable " + variable + " for user " + username); // TODO check valid - String querry = "DELETE FROM billing.vars WHERE username = '" +username + "' AND variable = '" + variable +"'"; + String querry = "DELETE FROM billing.vars WHERE username = '" + username + "' AND variable = '" + variable +"'"; jdbcTemplate.execute(querry); } } diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java index 82d4ecbec..87a408d5a 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java @@ -3,6 +3,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; import ru.mipt.java2016.homework.base.task1.Calculator; import ru.mipt.java2016.homework.base.task1.ParsingException; @@ -21,28 +22,19 @@ public class CalculatorController { @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 + "!

" + - ""; + public String main(Authentication authentication, @RequestParam(required = false) String name) { + String username = authentication.getName(); + return "Hello, " + username + ".\n"; } @RequestMapping(path = "/eval", method = RequestMethod.POST, consumes = "text/plain", produces = "text/plain") - public String evalPost(@RequestBody String expression) throws ParsingException { - LOG.debug("Evaluation request: [" + expression + "]"); + public String evalPost(Authentication authentication, @RequestBody String expression) throws ParsingException { + String username = authentication.getName(); + LOG.debug("Evaluation request: [" + expression + "] for user: " + username); String result; try { - double dResult = rebuildAndCalculate(expression, billingDao.getAllVariables("username")); // TODO username + double dResult = rebuildAndCalculate(expression, billingDao.getAllVariables(username)); // TODO username result = Double.toString(dResult) + "\n"; } catch (Throwable e) { result = "InvalidExpression.\n"; @@ -52,11 +44,6 @@ public String evalPost(@RequestBody String expression) throws ParsingException { return result; } - @RequestMapping(path = "/eval", method = RequestMethod.GET, produces = "text/html") - public String evalGet() throws ParsingException { - return "You should use POST method.\n"; - } - /*** Variables functions * GET /variable/${variableName} * @@ -70,15 +57,17 @@ public String evalGet() throws ParsingException { * TODO Remove this*/ @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.GET, produces = "text/html") - public String varGet(@PathVariable String variableName) throws ParsingException { - return billingDao.getVariable("username", variableName) + "\n"; + public String varGet(Authentication authentication, @PathVariable String variableName) throws ParsingException { + String username = authentication.getName(); + return billingDao.getVariable(username, variableName) + "\n"; } @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.PUT, produces = "text/html") - public String varPut(@PathVariable String variableName, @RequestBody String value) throws ParsingException { + public String varPut(Authentication authentication, @PathVariable String variableName, @RequestBody String value) throws ParsingException { + String username = authentication.getName(); String result = "OK\n"; try { - billingDao.setVariable("username", variableName, value); + billingDao.setVariable(username, variableName, value); } catch (Exception e) { result = "Server Internal Error.\n"; } @@ -86,10 +75,11 @@ public String varPut(@PathVariable String variableName, @RequestBody String valu } @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.DELETE, produces = "text/html") - public String varDel(@PathVariable String variableName) throws ParsingException { + public String varDel(Authentication authentication, @PathVariable String variableName) throws ParsingException { + String username = authentication.getName(); String result = "OK\n"; try { - billingDao.delVariable("username", variableName); + billingDao.delVariable(username, variableName); } catch (Exception e) { result = "Server Internal Error.\n"; } @@ -97,19 +87,18 @@ public String varDel(@PathVariable String variableName) throws ParsingException } @RequestMapping(path = "/variable/", method = RequestMethod.GET, produces = "text/html") - public String allVarGet() throws ParsingException { - List allVar = billingDao.getAllVariableNames("username"); // TODO Normal user + public String allVarGet(Authentication authentication) throws ParsingException { + String username = authentication.getName(); + List allVar = billingDao.getAllVariableNames(username); String all = "'"; for (Iterator i = allVar.iterator(); i.hasNext(); ) { all += i.next(); if (i.hasNext()) { all += "', '"; - } else { - all += "'"; } } - return all + "\n"; + return all + "'\n"; } /*** Function functions @@ -125,28 +114,32 @@ public String allVarGet() throws ParsingException { * TODO Remove this*/ @RequestMapping(path = "/function/{functionName}", method = RequestMethod.GET, produces = "text/html") - public String funcGet(@PathVariable String functionName) throws ParsingException { + public String funcGet(Authentication authentication, @PathVariable String functionName) throws ParsingException { + String username = authentication.getName(); return "Requested: " + functionName + "\n" + "This function doesn't implemented yet.\n"; } @RequestMapping(path = "/function/{functionName}", method = RequestMethod.PUT, produces = "text/html") - public String funcPut(@PathVariable String functionName, + public String funcPut(Authentication authentication, @PathVariable String functionName, @RequestParam(value = "args") List arguments, @RequestBody String request) throws ParsingException { + String username = authentication.getName(); return "An attempt to put: " + functionName + "\n" + "With request = " + request + "\n" + "This function doesn't implemented yet.\n"; } @RequestMapping(path = "/function/{functionName}", method = RequestMethod.DELETE, produces = "text/html") - public String funcDel(@PathVariable String functionName) throws ParsingException { + public String funcDel(Authentication authentication, @PathVariable String functionName) throws ParsingException { + String username = authentication.getName(); return "An attempt to delete: " + functionName + "\n" + "This function doesn't implemented yet.\n"; } @RequestMapping(path = "/function/", method = RequestMethod.GET, produces = "text/html") - public String allFuncGet() throws ParsingException { + public String allFuncGet(Authentication authentication) throws ParsingException { + String username = authentication.getName(); return "Requested all functions \n" + "This function doesn't implemented yet.\n"; } diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/SecurityServiceConfiguration.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/SecurityServiceConfiguration.java index a29cedd0d..0958a9eaf 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/SecurityServiceConfiguration.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/SecurityServiceConfiguration.java @@ -31,7 +31,7 @@ protected void configure(HttpSecurity http) throws Exception { .logout().disable() .csrf().disable() .authorizeRequests() - .antMatchers("/eval/**").authenticated() + .antMatchers("/**").authenticated() .anyRequest().permitAll(); } From 87f4bb2cb887fe445fc3e4db5452c7103746c35a Mon Sep 17 00:00:00 2001 From: shevkunov Date: Fri, 16 Dec 2016 22:09:38 +0300 Subject: [PATCH 5/8] =?UTF-8?q?=D0=A0=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D0=B5?= =?UTF-8?q?=D1=82=20=D0=B8=D0=BD=D1=82=D0=B5=D1=80=D1=84=D0=B5=D0=B9=D1=81?= =?UTF-8?q?=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B9.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../g594/shevkunov/task4/BillingDao.java | 68 ++++++++++++++++++ .../shevkunov/task4/CalculatorController.java | 35 +++++++--- .../g594/shevkunov/task4/FunctionWrapper.java | 69 +++++++++++++++++++ 3 files changed, 163 insertions(+), 9 deletions(-) create mode 100644 homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FunctionWrapper.java diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java index 5e4d5192c..6ff3f1f13 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java @@ -40,6 +40,10 @@ public void initSchema() { "(variable VARCHAR PRIMARY KEY, username VARCHAR," + //TODO FOREIGN KEY " value VARCHAR)"); + jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS billing.funcs " + + "(function VARCHAR PRIMARY KEY, username VARCHAR," + //TODO FOREIGN KEY + "args VARCHAR, value VARCHAR)"); + jdbcTemplate.execute("DELETE FROM billing.users WHERE username = 'username'"); jdbcTemplate.execute("DELETE FROM billing.users WHERE username = 'sudoname'"); jdbcTemplate.update("INSERT INTO billing.users VALUES ('username', 'password', TRUE) "); @@ -65,7 +69,9 @@ public BillingUser mapRow(ResultSet rs, int rowNum) throws SQLException { ); } + /** Variable functions */ public void setVariable(String username, String variable, String value) { + LOG.trace("Setting variable " + variable + " for user " + username); delVariable(username, variable); String querry = "INSERT INTO billing.vars VALUES ('" + variable + "','" + username + "','" + value + "')"; jdbcTemplate.execute(querry); @@ -118,4 +124,66 @@ public void delVariable(String username, String variable) { String querry = "DELETE FROM billing.vars WHERE username = '" + username + "' AND variable = '" + variable +"'"; jdbcTemplate.execute(querry); } + + + + /** Function functions */ + public void setFunction(String username, FunctionWrapper function) { + LOG.trace("Setting function " + function.getName() + " for user " + username); + delFunction(username, function.getName()); + String querry = "INSERT INTO billing.funcs VALUES ('" + function.getName() + + "','" + username + "','" + function.argsToString() + "','" + function.getValue() +"')"; + jdbcTemplate.execute(querry); + } + + public FunctionWrapper getFunction(String username, String function) { + LOG.trace("Getting function " + function + " for user " + username); + String querry = "SELECT * FROM billing.funcs WHERE username = '" + + username + "' AND function = '" + function + "'"; + return jdbcTemplate.queryForObject( + querry, + new RowMapper() { + @Override + public FunctionWrapper mapRow(ResultSet rs, int rowNum) throws SQLException { + return new FunctionWrapper(rs.getString("function"), + rs.getString("args"), rs.getString("value")); + } + } + ); + } + + public List getAllFunctionNames(String username) { + LOG.trace("Getting all functions for user " + username); + String querry = "SELECT function FROM billing.funcs WHERE username = '" + username + "'"; + + List vars = new ArrayList(); + + List> rows = jdbcTemplate.queryForList(querry); + + for (Map row : rows) { + vars.add((String)row.get("function")); + } + return vars; + } + + public Map getAllFunctions(String username) { + LOG.trace("Getting all functions for user " + username); + String querry = "SELECT * FROM billing.funcs WHERE username = '" + username + "'"; + + Map vars = new HashMap<>(); + + List> rows = jdbcTemplate.queryForList(querry); + for (Map row : rows) { + FunctionWrapper func = new FunctionWrapper((String)row.get("function"), + (String)row.get("args"), (String)row.get("value")); + vars.put(func.getName(), func); + } + return vars; + } + + public void delFunction(String username, String function) { + LOG.trace("Deletting function " + function + " for user " + username); // TODO check valid + String querry = "DELETE FROM billing.funcs WHERE username = '" + username + "' AND function = '" + function +"'"; + jdbcTemplate.execute(querry); + } } diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java index 87a408d5a..45a54728e 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java @@ -116,8 +116,8 @@ public String allVarGet(Authentication authentication) throws ParsingException { @RequestMapping(path = "/function/{functionName}", method = RequestMethod.GET, produces = "text/html") public String funcGet(Authentication authentication, @PathVariable String functionName) throws ParsingException { String username = authentication.getName(); - return "Requested: " + functionName + "\n" + - "This function doesn't implemented yet.\n"; + FunctionWrapper func = billingDao.getFunction(username, functionName); + return func.toString() + "\n"; } @RequestMapping(path = "/function/{functionName}", method = RequestMethod.PUT, produces = "text/html") @@ -125,23 +125,40 @@ public String funcPut(Authentication authentication, @PathVariable String functi @RequestParam(value = "args") List arguments, @RequestBody String request) throws ParsingException { String username = authentication.getName(); - return "An attempt to put: " + functionName + "\n" + - "With request = " + request + "\n" + - "This function doesn't implemented yet.\n"; + String result = "OK\n"; + try { + billingDao.setFunction(username, new FunctionWrapper(functionName, arguments, request)); + } catch (Exception e) { + result = "Server Internal Error.\n"; + } + return result; } @RequestMapping(path = "/function/{functionName}", method = RequestMethod.DELETE, produces = "text/html") public String funcDel(Authentication authentication, @PathVariable String functionName) throws ParsingException { String username = authentication.getName(); - return "An attempt to delete: " + functionName + "\n" + - "This function doesn't implemented yet.\n"; + String result = "OK\n"; + try { + billingDao.delFunction(username, functionName); + } catch (Exception e) { + result = "Server Internal Error.\n"; + } + return result; } @RequestMapping(path = "/function/", method = RequestMethod.GET, produces = "text/html") public String allFuncGet(Authentication authentication) throws ParsingException { String username = authentication.getName(); - return "Requested all functions \n" + - "This function doesn't implemented yet.\n"; + List allVar = billingDao.getAllFunctionNames(username); + String all = "'"; + for (Iterator i = allVar.iterator(); i.hasNext(); ) { + all += i.next(); + if (i.hasNext()) { + all += "', '"; + } + } + + return all + "'\n"; } private boolean isVariableChar(char ch) { diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FunctionWrapper.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FunctionWrapper.java new file mode 100644 index 000000000..b2194fa41 --- /dev/null +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FunctionWrapper.java @@ -0,0 +1,69 @@ +package ru.mipt.java2016.homework.g594.shevkunov.task4; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Created by shevkunov on 16.12.16. + */ +public class FunctionWrapper { + FunctionWrapper(String name, List args, String value) { + this.name = name; + this.value = value; + this.args = args; + } + + FunctionWrapper(String name, String args, String value) { + this.name = name; + this.value = value; + this.args = new ArrayList<>(); + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < args.length(); ++i) { + if (args.charAt(i) != SEPARATOR) { + sb.append(args.charAt(i)); + } else { + this.args.add(sb.toString()); + sb.delete(0, sb.length()); + } + } + + if (sb.length() > 0) { + this.args.add(sb.toString()); + } + } + + static final char SEPARATOR = ','; + private List args; + private String name; + private String value; + + public List getArgs() { + return args; + } + + public String getName() { + return name; + } + + public String getValue() { + return value; + } + + @Override + public String toString() { + return "Function name = [" + name + "], args = [" + argsToString() + "]" + ", value = [" + value + "]"; + } + + public String argsToString() { + String all = ""; + for (Iterator i = args.iterator(); i.hasNext(); ) { + all += i.next(); + if (i.hasNext()) { + all += ","; + } + } + return all; + } +} From 1034572a8b3dca7ce0a0f7bc452c09f4bcbe6393 Mon Sep 17 00:00:00 2001 From: shevkunov Date: Sat, 17 Dec 2016 02:26:19 +0300 Subject: [PATCH 6/8] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D1=80=D0=B5=D0=B3=D0=B8=D1=81=D1=82=D1=80=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D1=82=D0=B5=D0=BB=D1=8F.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../g594/shevkunov/task4/BillingDao.java | 14 ++ .../shevkunov/task4/CalculatorController.java | 73 +++++------ .../g594/shevkunov/task4/FunctionWrapper.java | 45 ++++--- .../task4/SecurityServiceConfiguration.java | 7 +- .../g594/shevkunov/task4/Substitutor.java | 123 ++++++++++++++++++ 5 files changed, 206 insertions(+), 56 deletions(-) create mode 100644 homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/Substitutor.java diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java index 6ff3f1f13..d8f79ca13 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java @@ -186,4 +186,18 @@ public void delFunction(String username, String function) { String querry = "DELETE FROM billing.funcs WHERE username = '" + username + "' AND function = '" + function +"'"; jdbcTemplate.execute(querry); } + + + /** Function functions */ + public boolean registerUser(String username, String password) { + LOG.trace("Registering user " + username); // TODO check valid + String querry = "SELECT COUNT(*) FROM billing.users WHERE username = '" + username + "'"; + int total = jdbcTemplate.queryForObject(querry, Integer.class); + if (total != 0) { + return false; + } + querry = "INSERT INTO billing.users VALUES ('" + username + "', '" + password + "', TRUE) "; + jdbcTemplate.execute(querry); + return true; + } } diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java index 45a54728e..827b38663 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java @@ -24,8 +24,28 @@ public class CalculatorController { @RequestMapping(path = "/", method = RequestMethod.GET, produces = "text/html") public String main(Authentication authentication, @RequestParam(required = false) String name) { - String username = authentication.getName(); - return "Hello, " + username + ".\n"; + if (authentication != null) { + String username = authentication.getName(); + return "Hello, " + username + ".\n"; + } else { + return "Hello, noname.\n"; + } + } + + @RequestMapping(path = "/user/{username}", method = RequestMethod.PUT, produces = "text/html") + public String userPut(Authentication authentication, @PathVariable String username, + @RequestBody String password) throws ParsingException { + String result; + try { + if (billingDao.registerUser(username, password)) { + result = "Registered."; + } else { + result = "Change username."; + } + } catch (Exception e) { + result = "Can't register this user."; + } + return result + "\n"; } @RequestMapping(path = "/eval", method = RequestMethod.POST, consumes = "text/plain", produces = "text/plain") @@ -34,7 +54,8 @@ public String evalPost(Authentication authentication, @RequestBody String expres LOG.debug("Evaluation request: [" + expression + "] for user: " + username); String result; try { - double dResult = rebuildAndCalculate(expression, billingDao.getAllVariables(username)); // TODO username + double dResult = rebuildAndCalculate(expression, billingDao.getAllVariables(username), + billingDao.getAllFunctions(username)); // TODO username result = Double.toString(dResult) + "\n"; } catch (Throwable e) { result = "InvalidExpression.\n"; @@ -65,13 +86,17 @@ public String varGet(Authentication authentication, @PathVariable String variabl @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.PUT, produces = "text/html") public String varPut(Authentication authentication, @PathVariable String variableName, @RequestBody String value) throws ParsingException { String username = authentication.getName(); - String result = "OK\n"; + String result = "OK"; try { + value = Double.toString(rebuildAndCalculate(value, billingDao.getAllVariables(username), + billingDao.getAllFunctions(username))); billingDao.setVariable(username, variableName, value); + } catch (ParsingException e){ + result = e.toString(); } catch (Exception e) { - result = "Server Internal Error.\n"; + result = "Server Internal Error."; } - return result; + return result + "\n"; } @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.DELETE, produces = "text/html") @@ -161,37 +186,9 @@ public String allFuncGet(Authentication authentication) throws ParsingException return all + "'\n"; } - private boolean isVariableChar(char ch) { - return Character.isAlphabetic(ch) || Character.isDigit(ch) || ch == '_'; - } - - private double rebuildAndCalculate(String expression, Map variables) throws ParsingException { - StringBuilder buffer = new StringBuilder(); - StringBuilder newExpression = new StringBuilder(); - - - for (int i = 0; i < expression.length(); ++i) { - if (isVariableChar(expression.charAt(i))) { - buffer.append(expression.charAt(i)); - } - - if (!isVariableChar(expression.charAt(i)) || (expression.length() == i + 1)) { - String proceed = buffer.toString(); - buffer.delete(0, buffer.length()); - - if (variables.containsKey(proceed)) { - newExpression.append(variables.get(proceed)); - } else { - newExpression.append(proceed); - } - - if (!isVariableChar(expression.charAt(i))) { - newExpression.append(expression.charAt(i)); - } - } - - - } - return calculator.calculate(newExpression.toString()); + private double rebuildAndCalculate(String expression, Map variables, + Map functions) throws ParsingException { + Substitutor sub = new Substitutor(variables, functions); + return calculator.calculate(sub.substitute(expression)); } } diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FunctionWrapper.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FunctionWrapper.java index b2194fa41..65b60fb53 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FunctionWrapper.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FunctionWrapper.java @@ -17,21 +17,7 @@ public class FunctionWrapper { FunctionWrapper(String name, String args, String value) { this.name = name; this.value = value; - this.args = new ArrayList<>(); - - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < args.length(); ++i) { - if (args.charAt(i) != SEPARATOR) { - sb.append(args.charAt(i)); - } else { - this.args.add(sb.toString()); - sb.delete(0, sb.length()); - } - } - - if (sb.length() > 0) { - this.args.add(sb.toString()); - } + this.args = stringToList(args); } static final char SEPARATOR = ','; @@ -57,8 +43,31 @@ public String toString() { } public String argsToString() { + return listToString(args); + } + + public static List stringToList(String s) { + List list = new ArrayList<>(); + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < s.length(); ++i) { + if (s.charAt(i) != SEPARATOR) { + sb.append(s.charAt(i)); + } else { + list.add(sb.toString()); + sb.delete(0, sb.length()); + } + } + + if (sb.length() > 0) { + list.add(sb.toString()); + } + return list; + } + + public static String listToString(List list) { String all = ""; - for (Iterator i = args.iterator(); i.hasNext(); ) { + for (Iterator i = list.iterator(); i.hasNext(); ) { all += i.next(); if (i.hasNext()) { all += ","; @@ -66,4 +75,8 @@ public String argsToString() { } return all; } + + public static boolean isVariableChar(char ch) { + return Character.isAlphabetic(ch) || Character.isDigit(ch) || ch == '_'; + } } diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/SecurityServiceConfiguration.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/SecurityServiceConfiguration.java index 0958a9eaf..d6f321cdd 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/SecurityServiceConfiguration.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/SecurityServiceConfiguration.java @@ -31,8 +31,11 @@ protected void configure(HttpSecurity http) throws Exception { .logout().disable() .csrf().disable() .authorizeRequests() - .antMatchers("/**").authenticated() - .anyRequest().permitAll(); + .antMatchers("/eval/**").authenticated() + .antMatchers("/variable/**").authenticated() + .antMatchers("/function/**").authenticated() + .anyRequest().permitAll() + ; } @Autowired diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/Substitutor.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/Substitutor.java new file mode 100644 index 000000000..4845864fe --- /dev/null +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/Substitutor.java @@ -0,0 +1,123 @@ +package ru.mipt.java2016.homework.g594.shevkunov.task4; + +import ru.mipt.java2016.homework.base.task1.ParsingException; + +import java.util.List; +import java.util.Map; + +/** + * Created by shevkunov on 17.12.16. + */ +public class Substitutor { + Substitutor(Map variables, + Map functions) { + this.variables = variables; + this.functions = functions; + } + + String functionSubstitute(FunctionWrapper function, String strArgs) throws ParsingException { + List substitutions = FunctionWrapper.stringToList(strArgs); + List args = function.getArgs(); + + for (int i = 0; i < substitutions.size(); ++i) { + substitutions.set(i, substitute(substitutions.get(i))); + } + + String value = function.getValue(); + + if (substitutions.size() != args.size()) { + throw new ParsingException("Bad arguments substitution."); + } + + StringBuilder res = new StringBuilder(); + for (int i = 0; i < value.length();) { + boolean substituted = false; + for (int j = 0; j < args.size(); ++j) { + String arg = args.get(j); + boolean stringComparable = (value.length() - i >= arg.length()) && + arg.equals(value.substring(i, i + arg.length())); + if (stringComparable) { // TODO So Sloow + boolean endedAtGoodSymbol = (value.length() - i == arg.length()) || + !FunctionWrapper.isVariableChar(value.charAt(i + arg.length())); + if (endedAtGoodSymbol) { + res.append(substitutions.get(j)); + i += arg.length(); + substituted = true; + break; + } + } + + res.append(value.charAt(i)); + ++i; + } + } + + return res.toString(); + } + + String substitute(String expression) throws ParsingException { + StringBuilder buffer = new StringBuilder(); + StringBuilder newExpression = new StringBuilder(); + + + for (int i = 0; i < expression.length(); ++i) { + if (FunctionWrapper.isVariableChar(expression.charAt(i))) { + buffer.append(expression.charAt(i)); + } + + if (!FunctionWrapper.isVariableChar(expression.charAt(i)) || (expression.length() == i + 1)) { + String proceed = buffer.toString(); + buffer.delete(0, buffer.length()); + + if (expression.charAt(i) == '(') { + // FUNCTION + if (functions.containsKey(proceed)) { + int rPos = i + 1; + int balance = 1; + while ((rPos < expression.length()) && (balance != 0)) { + switch (expression.charAt(rPos)) { + case '(': + ++balance; + break; + case ')': + --balance; + } + ++rPos; + } + + if (balance == 0) { + FunctionWrapper function = functions.get(proceed); + String substituted = functionSubstitute(function, expression.substring(i + 1, rPos - 1)); + newExpression.append(" ("); + newExpression.append(substituted); + newExpression.append(") "); + } else { + throw new ParsingException("Cannot substitude a function."); + } + + i = rPos - 1; + continue; + } else { + newExpression.append(proceed); + } + } else { + // VARIABLE + if (variables.containsKey(proceed)) { + newExpression.append(variables.get(proceed)); + } else { + newExpression.append(proceed); + } + } + + if (!FunctionWrapper.isVariableChar(expression.charAt(i))) { + newExpression.append(expression.charAt(i)); + } + } + } + + return newExpression.toString(); + } + + private Map variables; + private Map functions; +} From 4f61d728d49bbb84584b24f8347f03cb497ca3f4 Mon Sep 17 00:00:00 2001 From: shevkunov Date: Sat, 17 Dec 2016 11:58:31 +0300 Subject: [PATCH 7/8] =?UTF-8?q?=D0=94=D0=B5=D1=81=D1=8F=D1=82=D1=8C=20?= =?UTF-8?q?=D0=B8=D0=B7=20=D0=B4=D0=B5=D1=81=D1=8F=D1=82=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../g594/shevkunov/task4/BillingDao.java | 18 +- .../shevkunov/task4/CalculatorController.java | 21 +- .../shevkunov/task4/FediqApplication.java | 2 +- .../g594/shevkunov/task4/FunctionWrapper.java | 2 +- .../shevkunov/task4/PolishCalculator.java | 422 ------------------ .../task4/SecurityServiceConfiguration.java | 3 +- .../g594/shevkunov/task4/Substitutor.java | 12 +- 7 files changed, 35 insertions(+), 445 deletions(-) delete mode 100644 homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/PolishCalculator.java diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java index d8f79ca13..6afae673f 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java @@ -101,7 +101,7 @@ public List getAllVariableNames(String username) { List> rows = jdbcTemplate.queryForList(querry); for (Map row : rows) { - vars.add((String)row.get("variable")); + vars.add((String) row.get("variable")); } return vars; } @@ -114,14 +114,15 @@ public Map getAllVariables(String username) { List> rows = jdbcTemplate.queryForList(querry); for (Map row : rows) { - vars.put((String)row.get("variable"), (String)row.get("value")); + vars.put((String) row.get("variable"), (String) row.get("value")); } return vars; } public void delVariable(String username, String variable) { LOG.trace("Deletting variable " + variable + " for user " + username); // TODO check valid - String querry = "DELETE FROM billing.vars WHERE username = '" + username + "' AND variable = '" + variable +"'"; + String querry = "DELETE FROM billing.vars WHERE username = '" + username + + "' AND variable = '" + variable + "'"; jdbcTemplate.execute(querry); } @@ -132,7 +133,7 @@ public void setFunction(String username, FunctionWrapper function) { LOG.trace("Setting function " + function.getName() + " for user " + username); delFunction(username, function.getName()); String querry = "INSERT INTO billing.funcs VALUES ('" + function.getName() + - "','" + username + "','" + function.argsToString() + "','" + function.getValue() +"')"; + "','" + username + "','" + function.argsToString() + "','" + function.getValue() + "')"; jdbcTemplate.execute(querry); } @@ -161,7 +162,7 @@ public List getAllFunctionNames(String username) { List> rows = jdbcTemplate.queryForList(querry); for (Map row : rows) { - vars.add((String)row.get("function")); + vars.add((String) row.get("function")); } return vars; } @@ -174,8 +175,8 @@ public Map getAllFunctions(String username) { List> rows = jdbcTemplate.queryForList(querry); for (Map row : rows) { - FunctionWrapper func = new FunctionWrapper((String)row.get("function"), - (String)row.get("args"), (String)row.get("value")); + FunctionWrapper func = new FunctionWrapper((String) row.get("function"), + (String) row.get("args"), (String) row.get("value")); vars.put(func.getName(), func); } return vars; @@ -183,7 +184,8 @@ public Map getAllFunctions(String username) { public void delFunction(String username, String function) { LOG.trace("Deletting function " + function + " for user " + username); // TODO check valid - String querry = "DELETE FROM billing.funcs WHERE username = '" + username + "' AND function = '" + function +"'"; + String querry = "DELETE FROM billing.funcs WHERE username = '" + username + + "' AND function = '" + function + "'"; jdbcTemplate.execute(querry); } diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java index 827b38663..8a2d979fa 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java @@ -56,13 +56,13 @@ public String evalPost(Authentication authentication, @RequestBody String expres try { double dResult = rebuildAndCalculate(expression, billingDao.getAllVariables(username), billingDao.getAllFunctions(username)); // TODO username - result = Double.toString(dResult) + "\n"; + result = Double.toString(dResult); } catch (Throwable e) { - result = "InvalidExpression.\n"; + result = e.toString(); } LOG.trace("Result: " + result); - return result; + return result + "\n"; } /*** Variables functions @@ -84,14 +84,15 @@ public String varGet(Authentication authentication, @PathVariable String variabl } @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.PUT, produces = "text/html") - public String varPut(Authentication authentication, @PathVariable String variableName, @RequestBody String value) throws ParsingException { + public String varPut(Authentication authentication, @PathVariable String variableName, + @RequestBody String value) throws ParsingException { String username = authentication.getName(); String result = "OK"; try { value = Double.toString(rebuildAndCalculate(value, billingDao.getAllVariables(username), billingDao.getAllFunctions(username))); billingDao.setVariable(username, variableName, value); - } catch (ParsingException e){ + } catch (ParsingException e) { result = e.toString(); } catch (Exception e) { result = "Server Internal Error."; @@ -102,13 +103,13 @@ public String varPut(Authentication authentication, @PathVariable String variabl @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.DELETE, produces = "text/html") public String varDel(Authentication authentication, @PathVariable String variableName) throws ParsingException { String username = authentication.getName(); - String result = "OK\n"; + String result = "OK"; try { billingDao.delVariable(username, variableName); } catch (Exception e) { - result = "Server Internal Error.\n"; + result = e.toString(); } - return result; + return result + "\n"; } @RequestMapping(path = "/variable/", method = RequestMethod.GET, produces = "text/html") @@ -116,7 +117,7 @@ public String allVarGet(Authentication authentication) throws ParsingException { String username = authentication.getName(); List allVar = billingDao.getAllVariableNames(username); String all = "'"; - for (Iterator i = allVar.iterator(); i.hasNext(); ) { + for (Iterator i = allVar.iterator(); i.hasNext();) { all += i.next(); if (i.hasNext()) { all += "', '"; @@ -176,7 +177,7 @@ public String allFuncGet(Authentication authentication) throws ParsingException String username = authentication.getName(); List allVar = billingDao.getAllFunctionNames(username); String all = "'"; - for (Iterator i = allVar.iterator(); i.hasNext(); ) { + for (Iterator i = allVar.iterator(); i.hasNext();) { all += i.next(); if (i.hasNext()) { all += "', '"; diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FediqApplication.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FediqApplication.java index fd0eb8fbd..19118d548 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FediqApplication.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FediqApplication.java @@ -24,7 +24,7 @@ public class FediqApplication { @Bean public Calculator calculator() { - return new PolishCalculator(); + return new ru.mipt.java2016.homework.g594.shevkunov.task1.PolishCalculator(); } @Bean diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FunctionWrapper.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FunctionWrapper.java index 65b60fb53..1a10e4cd8 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FunctionWrapper.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/FunctionWrapper.java @@ -67,7 +67,7 @@ public static List stringToList(String s) { public static String listToString(List list) { String all = ""; - for (Iterator i = list.iterator(); i.hasNext(); ) { + for (Iterator i = list.iterator(); i.hasNext();) { all += i.next(); if (i.hasNext()) { all += ","; diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/PolishCalculator.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/PolishCalculator.java deleted file mode 100644 index d793c7205..000000000 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/PolishCalculator.java +++ /dev/null @@ -1,422 +0,0 @@ -package ru.mipt.java2016.homework.g594.shevkunov.task4; - -import ru.mipt.java2016.homework.base.task1.Calculator; -import ru.mipt.java2016.homework.base.task1.ParsingException; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Stack; - -/** - * Evaluates a value from expressing - * Created by shevkunov on 04.10.16. - */ -public class PolishCalculator implements Calculator { - private Stack valStack = new Stack<>(); - private Stack operStack = new Stack<>(); - private StringBuilder buffer = new StringBuilder(); - private ParserState state = ParserState.NONE; - private boolean unary = true; - - public double calculate(String expression) throws ParsingException { - if (expression == null) { - throw new ParsingException("Null expression."); - } else { - if (expression.length() == 0) { - throw new ParsingException("I think, the result are 42."); - } else { - return parse(expression); - } - } - } - - private void proceedOperation(Operation eval) throws ParsingException { - if (eval.isBracket()) { - throw new ParsingException("Incorrect expression."); - } - double[] args = new double[eval.valence()]; - for (int argIndex = args.length - 1; argIndex >= 0; --argIndex) { - if (!valStack.isEmpty()) { - args[argIndex] = valStack.pop(); - } else { - throw new ParsingException("Incorrect expression."); - } - } - valStack.push(eval.evaluate(args)); - } - - private void pushOperation(String opString, boolean isUnary) throws ParsingException { - Operation op = - isUnary ? Operation.getOperation("U" + opString) : Operation.getOperation(opString); - if (null != op) { // Yoda style - if (!op.isBracket()) { - while (!operStack.isEmpty() && ( - ((operStack.peek().valence() != 1) && operStack.peek().notWeakerThan(op)) - || (operStack.peek().valence() == 1) && operStack.peek() - .strongerThan(op))) { - proceedOperation(operStack.pop()); - } - operStack.push(op); - } else { - if (op.closeBracket() == null) { - operStack.push(op); - } else { - while (!operStack.isEmpty() && (operStack.peek() != op.closeBracket())) { - proceedOperation(operStack.pop()); - } - if (operStack.isEmpty()) { - throw new ParsingException("Incorrect expression."); - } else { - operStack.pop(); - } - } - } - } else { - throw new ParsingException("Unknown operation : " + opString); - } - } - - private void pushBuffer() throws ParsingException { - switch (state) { - case OPER: - pushOperation(buffer.toString(), unary); - unary = true; - break; - case VAL: - try { - valStack.push(Double.parseDouble(buffer.toString())); - } catch (NumberFormatException e) { - throw new ParsingException("Bad number."); - } - unary = false; - break; - default: - // do nothing - } - buffer.delete(0, buffer.length()); - } - - private double parse(String expr) throws ParsingException { - unary = true; - state = ParserState.NONE; - for (int i = 0; i < expr.length(); ++i) { - if (Character.isDigit(expr.charAt(i)) || (expr.charAt(i) == '.')) { - if (state != ParserState.VAL) { - pushBuffer(); - state = ParserState.VAL; - } - buffer.append(expr.charAt(i)); - } else { - if (Character.isWhitespace(expr.charAt(i))) { - pushBuffer(); - state = ParserState.NONE; - } else { - if (state != ParserState.OPER) { - pushBuffer(); - state = ParserState.OPER; - } - buffer.append(expr.charAt(i)); - Operation readed = Operation - .getOperation(unary ? "U" + buffer.toString() : buffer.toString()); - if (null != readed) { - if (readed.isBracket()) { - unary = false; - pushBuffer(); - state = ParserState.NONE; - unary = readed.closeBracket() == null; - } else { - if ((!operStack.empty()) && (operStack.peek() == Operation.UNARYPLUS) - && (readed == Operation.UNARYPLUS)) { - throw new ParsingException("I love ++i"); - // I think that ++1 is correct; - // this is ony for testPlusPlus - } - pushBuffer(); - unary = true; - state = ParserState.NONE; - } - } - } - } - } - pushBuffer(); - - while (!operStack.isEmpty()) { - proceedOperation(operStack.pop()); - } - if (valStack.size() != 1) { - throw new ParsingException("Incorrect expression."); - } - return valStack.pop(); - } - - private enum ParserState { - OPER, VAL, NONE - } - - - private enum Operation { - PLUS(0) { - @Override - public double compute(double... args) { - double result = 0.; // neutral element - for (double value : args) { - result += value; - } - return result; - } - }, MINUS(0) { - @Override - public double compute(double... args) { - if (args.length == 1) { - return 0. - args[0]; - } else { - if (args.length > 1) { - double result = args[0]; - for (int i = 1; i < args.length; ++i) { - result -= args[i]; - } - return result; - } else { - return 0.; // neutral element - } - } - } - }, MULTIPLY(1) { - @Override - public double compute(double... args) { - double result = 1.; //neutral elent - for (double value : args) { - result *= value; - } - return result; - } - }, DIVISION(1) { - @Override - public double compute(double... args) { - if (args.length == 1) { - return 1. / args[0]; - } else { - if (args.length > 1) { - double result = args[0]; - for (int i = 1; i < args.length; ++i) { - result /= args[i]; - } - return result; - } else { - return 1.; // neutral element - } - } - } - }, UNARYPLUS(777) { - @Override - public int valence() { - return 1; - } - - @Override - public double compute(double... args) { - return +args[0]; - } - }, UNARYMINUS(777) { - @Override - public int valence() { - return 1; - } - - @Override - public double compute(double... args) { - return -args[0]; - } - }, OPENBRAСKET(-1) { - @Override - public int valence() { - return 0; - } - - @Override - public boolean isBracket() { - return true; - } - - @Override - public double compute(double... args) { - return Double.NaN; - } - }, CLOSEBRAСKET(-1) { - @Override - public int valence() { - return 0; - } - - @Override - public boolean isBracket() { - return true; - } - - @Override - public PolishCalculator.Operation closeBracket() { - return PolishCalculator.Operation.OPENBRAСKET; - } - - @Override - public double compute(double... args) { - return Double.NaN; - } - }, SIN(2) { - @Override - public int valence() { - return 1; - } - - @Override - public double compute(double... args) { - return Math.sin(args[0]); - } - }, COS(2) { - @Override - public int valence() { - return 1; - } - - @Override - public double compute(double... args) { - return Math.cos(args[0]); - } - }, TG(2) { - @Override - public int valence() { - return 1; - } - - @Override - public double compute(double... args) { - return Math.tan(args[0]); - } - }, SQRT(2) { - @Override - public int valence() { - return 1; - } - - @Override - public double compute(double... args) { - return Math.sqrt(args[0]); - } - }, ABS(2) { - @Override - public int valence() { - return 1; - } - - @Override - public double compute(double... args) { - return Math.abs(args[0]); - } - }, SIGN(2) { - @Override - public int valence() { - return 1; - } - - @Override - public double compute(double... args) { - return Math.signum(args[0]); - } - } , LOG2(2) { - @Override - public int valence() { - return 1; - } - - @Override - public double compute(double... args) { - return Math.log(args[0]) / Math.log(2.); - } - }, POW(3) { - @Override - public double compute(double... args) { - return Math.pow(args[0], args[1]); - } - }, LOG(3) { - @Override - public double compute(double... args) { - return Math.log(args[0]) / Math.log(args[1]); - } - }, MAX(3) { - @Override - public double compute(double... args) { - return Math.max(args[0], args[1]); - } - }, MIN(4) { - @Override - public double compute(double... args) { - return Math.min(args[0], args[1]); - } - }; - // TODO RND - - private static final Map STRING_REPRESENTATIONS; - - static { - Map map = new HashMap<>(); - map.put("+", Operation.PLUS); - map.put("-", Operation.MINUS); - map.put("*", Operation.MULTIPLY); - map.put("/", Operation.DIVISION); - map.put("U+", Operation.UNARYPLUS); - map.put("U-", Operation.UNARYMINUS); - map.put("(", Operation.OPENBRAСKET); - map.put(")", Operation.CLOSEBRAСKET); - - map.put("U(", Operation.OPENBRAСKET); - map.put("U)", Operation.CLOSEBRAСKET); - - STRING_REPRESENTATIONS = Collections.unmodifiableMap(map); - } - - private final int order; - - Operation(int order) { - this.order = order; - } - - public static Operation getOperation(String name) { - if (STRING_REPRESENTATIONS.containsKey(name)) { - return STRING_REPRESENTATIONS.get(name); - } else { - return null; - } - } - - protected abstract double compute(double[] args); - - public double evaluate(double... args) throws ParsingException { - if (valence() != args.length) { - throw new ParsingException("Invalid valence."); - } - return compute(args); - } - - public boolean isBracket() { - return false; - } - - public Operation closeBracket() { - return null; // not a (close) bracket - } - - public int valence() { - return 2; // default - } - - public boolean strongerThan(Operation op) { - return this.order > op.order; - } - - public boolean notWeakerThan(Operation op) { - return this.order >= op.order; - } - } -} diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/SecurityServiceConfiguration.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/SecurityServiceConfiguration.java index d6f321cdd..79eab9581 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/SecurityServiceConfiguration.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/SecurityServiceConfiguration.java @@ -34,8 +34,7 @@ protected void configure(HttpSecurity http) throws Exception { .antMatchers("/eval/**").authenticated() .antMatchers("/variable/**").authenticated() .antMatchers("/function/**").authenticated() - .anyRequest().permitAll() - ; + .anyRequest().permitAll(); } @Autowired diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/Substitutor.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/Substitutor.java index 4845864fe..19ad4b19d 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/Substitutor.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/Substitutor.java @@ -52,10 +52,15 @@ String functionSubstitute(FunctionWrapper function, String strArgs) throws Parsi } } - return res.toString(); + return substitute(res.toString()); } String substitute(String expression) throws ParsingException { + ++level; + if (level > maximumLevel) { + level = 0; + throw new ParsingException("So deep..."); + } StringBuilder buffer = new StringBuilder(); StringBuilder newExpression = new StringBuilder(); @@ -81,6 +86,8 @@ String substitute(String expression) throws ParsingException { break; case ')': --balance; + break; + default: } ++rPos; } @@ -115,9 +122,12 @@ String substitute(String expression) throws ParsingException { } } + --level; return newExpression.toString(); } private Map variables; private Map functions; + private int level = 0; + private final int maximumLevel = 1000; } From b80eedcbfa9659d59eebdbef5b4f9ff1fea9a78c Mon Sep 17 00:00:00 2001 From: shevkunov Date: Sat, 17 Dec 2016 12:40:46 +0300 Subject: [PATCH 8/8] =?UTF-8?q?=D0=9E=D0=B4=D0=B8=D0=BD=D0=BD=D0=B0=D0=B4?= =?UTF-8?q?=D1=86=D0=B0=D1=82=D1=8C=20=D0=B8=D0=B7=20=D0=B4=D0=B5=D1=81?= =?UTF-8?q?=D1=8F=D1=82=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../homework/g594/shevkunov/task4/BillingDao.java | 2 +- .../g594/shevkunov/task4/CalculatorController.java | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java index 6afae673f..f01caf81f 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/BillingDao.java @@ -41,7 +41,7 @@ public void initSchema() { " value VARCHAR)"); jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS billing.funcs " + - "(function VARCHAR PRIMARY KEY, username VARCHAR," + //TODO FOREIGN KEY + "(function VARCHAR, username VARCHAR," + //TODO FOREIGN KEY "args VARCHAR, value VARCHAR)"); jdbcTemplate.execute("DELETE FROM billing.users WHERE username = 'username'"); diff --git a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java index 8a2d979fa..17f1c847f 100644 --- a/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java +++ b/homework-g594-shevkunov/src/main/java/ru/mipt/java2016/homework/g594/shevkunov/task4/CalculatorController.java @@ -80,7 +80,13 @@ public String evalPost(Authentication authentication, @RequestBody String expres @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.GET, produces = "text/html") public String varGet(Authentication authentication, @PathVariable String variableName) throws ParsingException { String username = authentication.getName(); - return billingDao.getVariable(username, variableName) + "\n"; + String value; + try { + value = billingDao.getVariable(username, variableName); + } catch (Exception e) { + value = e.toString(); + } + return value + "\n"; } @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.PUT, produces = "text/html") @@ -151,13 +157,13 @@ public String funcPut(Authentication authentication, @PathVariable String functi @RequestParam(value = "args") List arguments, @RequestBody String request) throws ParsingException { String username = authentication.getName(); - String result = "OK\n"; + String result = "OK"; try { billingDao.setFunction(username, new FunctionWrapper(functionName, arguments, request)); } catch (Exception e) { - result = "Server Internal Error.\n"; + result = e.toString(); } - return result; + return result + "\n"; } @RequestMapping(path = "/function/{functionName}", method = RequestMethod.DELETE, produces = "text/html")