From 2de4d672638bfe52cfc3f419f9910c61f1bfda11 Mon Sep 17 00:00:00 2001 From: bintang433 <13521003@std.stei.itb.ac.id> Date: Fri, 17 Nov 2023 06:56:17 +0700 Subject: [PATCH] feat: Driver, logger --- travelution-soap.sql | 14 ++ travelution/config.properties | 6 + travelution/pom.xml | 67 ++++++ .../main/java/com/example/travelution/DB.java | 27 +++ .../java/com/example/travelution/Web.java | 26 +++ .../travelution/driver/ISubscription.java | 33 +++ .../travelution/driver/Subscription.java | 193 ++++++++++++++++++ .../com/example/travelution/log/Logger.java | 82 ++++++++ .../request/SubscriptionApprovalReq.java | 2 +- .../request/ValidateSubscriptionReq.java | 2 +- .../travelution/response/Response.java | 3 + .../response/SubscriptionApprovalResp.java | 3 + .../response/SubscriptionListResp.java | 3 + .../response/SubscriptionListWrapper.java | 3 + .../response/SubscriptionResp.java | 3 + .../response/ValidateSubscriptionResp.java | 3 + 16 files changed, 468 insertions(+), 2 deletions(-) create mode 100644 travelution-soap.sql create mode 100644 travelution/config.properties create mode 100644 travelution/pom.xml create mode 100644 travelution/src/main/java/com/example/travelution/DB.java create mode 100644 travelution/src/main/java/com/example/travelution/Web.java create mode 100644 travelution/src/main/java/com/example/travelution/driver/ISubscription.java create mode 100644 travelution/src/main/java/com/example/travelution/driver/Subscription.java create mode 100644 travelution/src/main/java/com/example/travelution/log/Logger.java diff --git a/travelution-soap.sql b/travelution-soap.sql new file mode 100644 index 0000000..57de2ff --- /dev/null +++ b/travelution-soap.sql @@ -0,0 +1,14 @@ +CREATE TABLE logging ( + id INT AUTO_INCREMENT PRIMARY KEY, + description VARCHAR(256) NOT NULL, + IP VARCHAR(16) NOT NULL, + endpoint VARCHAR(256) NOT NULL, + req_time TIMESTAMP NOT NULL +); + +CREATE TABLE subscription ( + creator_id INT NOT NULL, + subscriber_id INT NOT NULL, + status ENUM ('PENDING', 'ACCEPTED', 'REJECTED') NOT NULL DEFAULT 'PENDING', + PRIMARY KEY (creator_id, subscriber_id) +); \ No newline at end of file diff --git a/travelution/config.properties b/travelution/config.properties new file mode 100644 index 0000000..88e93ae --- /dev/null +++ b/travelution/config.properties @@ -0,0 +1,6 @@ +DB_URL="jdbc:mysql://host:port/databaseName" +DB_USERNAME= +DB_PASSWORD= + +BASE_URL= +API_KEY= \ No newline at end of file diff --git a/travelution/pom.xml b/travelution/pom.xml new file mode 100644 index 0000000..9bb5f01 --- /dev/null +++ b/travelution/pom.xml @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>com.example</groupId> + <artifactId>travelution</artifactId> + <version>1.0-SNAPSHOT</version> + <name>travelution</name> + <packaging>war</packaging> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <maven.compiler.target>1.8</maven.compiler.target> + <maven.compiler.source>1.8</maven.compiler.source> + <junit.version>5.9.2</junit.version> + </properties> + +<repositories> + <repository> + <id>central</id> + <url>https://repo.maven.apache.org/maven2</url> + </repository> +</repositories> + + <dependencies> +<dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <version>4.0.1</version> + <scope>provided</scope> + </dependency><dependency> + <groupId>javax.xml.ws</groupId> + <artifactId>jaxws-api</artifactId> + <version>2.3.1</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>javax.jws</groupId> + <artifactId>javax.jws-api</artifactId> + <version>1.1</version> + <scope>provided</scope> + </dependency> +<dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-api</artifactId> + <version>${junit.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <version>${junit.version}</version> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-war-plugin</artifactId> + <version>3.3.2</version> + </plugin> </plugins> + </build> +</project> \ No newline at end of file diff --git a/travelution/src/main/java/com/example/travelution/DB.java b/travelution/src/main/java/com/example/travelution/DB.java new file mode 100644 index 0000000..5661bf8 --- /dev/null +++ b/travelution/src/main/java/com/example/travelution/DB.java @@ -0,0 +1,27 @@ +package com.example.travelution; + +import java.sql.Connection; +import java.sql.DriverManager; + +public class DB { + private Connection connection; + + public DB() { + try { + System.out.println("Connecting to MySQL Database"); + this.connection = DriverManager.getConnection( + System.getProperty("DB_URL"), + System.getProperty("DB_USERNAME"), + System.getProperty("DB_PASSWORD") + ); + System.out.println("Database connected!"); + } catch (Exception e) { + e.printStackTrace(); + System.out.println("Error on connecting to database"); + } + } + + public Connection getConnection() { + return this.connection; + } +} diff --git a/travelution/src/main/java/com/example/travelution/Web.java b/travelution/src/main/java/com/example/travelution/Web.java new file mode 100644 index 0000000..f7d4d78 --- /dev/null +++ b/travelution/src/main/java/com/example/travelution/Web.java @@ -0,0 +1,26 @@ +package com.example.travelution; + +import com.example.travelution.driver.Subscription; + +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.sql.Connection; +import java.util.Properties; + +import javax.xml.ws.Endpoint; + +public class Web { + public static void main( String[] args ) throws IOException, InterruptedException { + Properties properties = new Properties(); + try (InputStream input = Files.newInputStream(Paths.get("../../../../../../../config.properties"))) { + properties.load(input); + } catch (Exception e) { + e.printStackTrace(); + } + DB db = new DB(); + Connection db_conn = db.getConnection(); + + Endpoint.publish(properties.getProperty("BASE_URL") + "/subscription", new Subscription(db_conn)); + } +} \ No newline at end of file diff --git a/travelution/src/main/java/com/example/travelution/driver/ISubscription.java b/travelution/src/main/java/com/example/travelution/driver/ISubscription.java new file mode 100644 index 0000000..0ea8a33 --- /dev/null +++ b/travelution/src/main/java/com/example/travelution/driver/ISubscription.java @@ -0,0 +1,33 @@ +package com.example.travelution.driver; + +import com.example.travelution.request.*; +import com.example.travelution.response.*; + +import javax.jws.WebMethod; +import javax.jws.WebParam; +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; + +@WebService +@SOAPBinding(style = SOAPBinding.Style.DOCUMENT) +public interface ISubscription { + @WebMethod(action = "\"requestSubscription\"") + SubscriptionResp requestSubscription( + @WebParam(name="request") SubscriptionReq subReq + ); + + @WebMethod(action = "\"approveOrRejectSubscription\"") + SubscriptionApprovalResp approveOrRejectSubscription( + @WebParam(name="request") SubscriptionApprovalReq subApprovalReq + ); + + @WebMethod(action = "\"listRequestSubscription\"") + SubscriptionListResp listRequestSubscription( + @WebParam(name="request") SubscriptionListReq subListReq + ); + + @WebMethod(action = "\"validateSubscription\"") + ValidateSubscriptionResp validateSubscription( + @WebParam(name="request") ValidateSubscriptionReq valSub + ); +} diff --git a/travelution/src/main/java/com/example/travelution/driver/Subscription.java b/travelution/src/main/java/com/example/travelution/driver/Subscription.java new file mode 100644 index 0000000..f16b142 --- /dev/null +++ b/travelution/src/main/java/com/example/travelution/driver/Subscription.java @@ -0,0 +1,193 @@ +package com.example.travelution.driver; + + +import com.example.travelution.log.Logger; +import com.example.travelution.request.*; +import com.example.travelution.response.*; + +import javax.annotation.Resource; +import javax.jws.WebService; +import javax.servlet.http.HttpServletRequest; +import javax.xml.ws.WebServiceContext; +import javax.xml.ws.handler.MessageContext; + + +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.Statement; +import java.time.LocalDateTime; +import java.util.*; + +@WebService(endpointInterface = "travelution.driver.ISubscription") +public class Subscription implements ISubscription{ + @Resource + WebServiceContext wsContext; + + private Connection db_conn; + private Logger logger; + + private final Properties properties = new Properties(); + + public Subscription() { + + } + public Subscription(Connection db_conn) { + this.db_conn = db_conn; + this.logger = new Logger(db_conn); + try (InputStream input = Files.newInputStream(Paths.get("../../../../../../../config.properties"))) { + properties.load(input); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public SubscriptionResp requestSubscription(SubscriptionReq reqSub) { + LocalDateTime timestamp = LocalDateTime.now(); + String IPAddress = this.getRequestIPAddress(); + + SubscriptionResp resp; + + if (!properties.getProperty("API_KEY").equals(reqSub.API_KEY)) { + resp = new SubscriptionResp(false, "Not Authorized", null, null); + } else { + try { + Statement statement = this.db_conn.createStatement(); + String sql = "INSERT INTO subscription(subscriber_id, status) " + + "VALUES (%d, '%s')"; + String formattedSql = String.format(sql, reqSub.subscriberId, "PENDING"); + int count = statement.executeUpdate(formattedSql); + if (count == 1) { + resp = new SubscriptionResp(true, "Added new subscription request", reqSub.subscriberId, "PENDING"); + } else { + resp = new SubscriptionResp(true, "Subscription request failed", reqSub.subscriberId, null); + } + } catch (Exception e) { + e.printStackTrace(); + resp = new SubscriptionResp(false, e.getMessage(), null, null); + } + } + + this.logger.generateLogging(timestamp, IPAddress, reqSub, resp); + return resp; + } + + @Override + public SubscriptionApprovalResp approveOrRejectSubscription(SubscriptionApprovalReq appOrRej) { + LocalDateTime timestamp = LocalDateTime.now(); + String IPAddress = this.getRequestIPAddress(); + + SubscriptionApprovalResp resp; + + if (!properties.getProperty("API_KEY").equals(appOrRej.API_KEY)) { + resp = new SubscriptionApprovalResp(false, "Not Authorized", null, null); + } else { + try { + Statement statement = this.db_conn.createStatement(); + String sql = + "UPDATE subscription " + + "SET status = '%s' " + + "WHERE " + + "subscriber_id = %d"; + + String appOrRejString = appOrRej.approve ? "ACCEPTED": "REJECTED"; + String formattedSql = String.format(sql, appOrRejString, appOrRej.subscriberId); + int count = statement.executeUpdate(formattedSql); + if (count == 1) { + String message = appOrRejString + " subscription successfully"; + resp = new SubscriptionApprovalResp(true, message, appOrRej.subscriberId, appOrRejString); + } else { + String message = appOrRejString + " subscription failed"; + resp = new SubscriptionApprovalResp(false, message, appOrRej.subscriberId, null); + } + + } catch (Exception e) { + e.printStackTrace(); + resp = new SubscriptionApprovalResp(false, e.getMessage(), null, null); + } + } + + this.logger.generateLogging(timestamp, IPAddress, appOrRej, resp); + return resp; + } + + @Override + public SubscriptionListResp listRequestSubscription(SubscriptionListReq listReqSub) { + LocalDateTime timestamp = LocalDateTime.now(); + String IPAddress = this.getRequestIPAddress(); + + SubscriptionListResp resp; + + if (!properties.getProperty("API_KEY").equals(listReqSub.API_KEY)) { + resp = new SubscriptionListResp(false, "Not Authorized", null); + } else { + try { + Statement statement = this.db_conn.createStatement(); + String sql = "SELECT * FROM subscription WHERE status = 'PENDING'"; + ResultSet resultSet = statement.executeQuery(sql); + List<Subscriber> listResp = new ArrayList<>(); + while (resultSet.next()) { + listResp.add(new Subscriber( + resultSet.getInt("subscriber_id"), + resultSet.getString("status") + )); + } + String message = "Subscription request list fetched successfully"; + resp = new SubscriptionListResp(true, message, listResp); + + } catch (Exception e) { + e.printStackTrace(); + resp = new SubscriptionListResp(false, e.getMessage(), null); + } + } + + this.logger.generateLogging(timestamp, IPAddress, listReqSub, resp); + return resp; + } + + @Override + public ValidateSubscriptionResp validateSubscription(ValidateSubscriptionReq valSub) { + LocalDateTime timestamp = LocalDateTime.now(); + String IPAddress = this.getRequestIPAddress(); + + ValidateSubscriptionResp resp; + + if (!properties.getProperty("API_KEY").equals(valSub.API_KEY)) { + resp = new ValidateSubscriptionResp(false, "Not Authorized", null, null); + } else { + try { + Statement statement = this.db_conn.createStatement(); + String sql = "SELECT * FROM subscription WHERE subscriber_id = " + valSub.subscriberId; + ResultSet resultSet = statement.executeQuery(sql); + + Subscriber subscription = null; + if (resultSet.next()) { + subscription = new Subscriber( + resultSet.getInt("subscriber_id"), + resultSet.getString("status") + ); + } + String message = "Subscription validation fetched successfully"; + boolean subscribed = subscription != null && subscription.status.equals("ACCEPTED"); + + resp = new ValidateSubscriptionResp(true, message, valSub.subscriberId, subscribed); + + } catch (Exception e) { + e.printStackTrace(); + resp = new ValidateSubscriptionResp(false, e.getMessage(), null, null); + } + } + + this.logger.generateLogging(timestamp, IPAddress, valSub, resp); + return resp; + } + + public String getRequestIPAddress() { + MessageContext messageContext = wsContext.getMessageContext(); + HttpServletRequest httpServletRequest = (HttpServletRequest) messageContext.get(MessageContext.SERVLET_REQUEST); + return httpServletRequest.getRemoteAddr(); + } +} diff --git a/travelution/src/main/java/com/example/travelution/log/Logger.java b/travelution/src/main/java/com/example/travelution/log/Logger.java new file mode 100644 index 0000000..d3322e5 --- /dev/null +++ b/travelution/src/main/java/com/example/travelution/log/Logger.java @@ -0,0 +1,82 @@ +package com.example.travelution.log; + +import com.example.travelution.request.*; +import com.example.travelution.response.*; + +import java.sql.Connection; +import java.sql.Statement; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public class Logger { + private Connection db_conn; + + public Logger(Connection db_conn) { + this.db_conn = db_conn; + } + + public void generateLogging(LocalDateTime timestamp, String IPAddress, Request req, Response resp) { + DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + StringBuilder descriptionBuilder = new StringBuilder(); + String endpoint = ""; + + if (!resp.success && resp.message.equals("Not Authorized")) { + descriptionBuilder.append("request rejected"); + } else { + if (req instanceof SubscriptionReq && resp instanceof SubscriptionResp) { + SubscriptionReq reqCasted = (SubscriptionReq) req; + descriptionBuilder.append("Request subscription for subscriber_id = " + reqCasted.subscriberId); + endpoint = "Subscription Request "; + + } else if (req instanceof SubscriptionListReq && resp instanceof SubscriptionListResp) { + descriptionBuilder.append("Request list of all subscription with status \"PENDING\""); + endpoint = "Subscription List"; + + } else if (req instanceof ValidateSubscriptionReq && resp instanceof ValidateSubscriptionResp) { + ValidateSubscriptionReq reqCasted = (ValidateSubscriptionReq) req; + ValidateSubscriptionResp respCasted = (ValidateSubscriptionResp) resp; + descriptionBuilder.append( + "Request validate subscription for subscriber_id = " + reqCasted.subscriberId + + ", validation result is " + respCasted.subscribed + ); + endpoint = "Validate Subscription"; + + } else if (req instanceof SubscriptionApprovalReq && resp instanceof SubscriptionApprovalResp) { + SubscriptionApprovalReq reqCasted = (SubscriptionApprovalReq) req; + SubscriptionApprovalResp respCasted = (SubscriptionApprovalResp) resp; + descriptionBuilder.append( + "Request to " + (reqCasted.approve ? "approve" : "reject") + " subscription request for subscriber_id = " + reqCasted.subscriberId + + ", subscription request " + respCasted.status + ); + endpoint = "Subscription Approval"; + + } else { + descriptionBuilder.append("Invalid request format"); + } + + if (resp.success) { + descriptionBuilder.append(", successful"); + } else { + descriptionBuilder.append(", failed"); + } + } + try { + String description = descriptionBuilder.toString(); + String timestampString = dtf.format(timestamp); + Statement statement = this.db_conn.createStatement(); + String sql = "INSERT INTO logging(description, IP, endpoint, req_time) " + + "VALUES ('%s', '%s', '%s', '%s')"; + + String formattedSql = String.format(sql, description, IPAddress, endpoint, timestampString); + int count = statement.executeUpdate(formattedSql); + if (count == 1) { + System.out.println("Log added"); + } else { + System.out.println("Failed to add log"); + } + } catch (Exception e) { + e.printStackTrace(); + System.out.println("Failed to add log"); + } + } +} diff --git a/travelution/src/main/java/com/example/travelution/request/SubscriptionApprovalReq.java b/travelution/src/main/java/com/example/travelution/request/SubscriptionApprovalReq.java index d27c5f9..1f97126 100644 --- a/travelution/src/main/java/com/example/travelution/request/SubscriptionApprovalReq.java +++ b/travelution/src/main/java/com/example/travelution/request/SubscriptionApprovalReq.java @@ -1,6 +1,6 @@ package com.example.travelution.request; -public class SubscriptionApprovalReq { +public class SubscriptionApprovalReq extends Request{ public int subscriberId; public boolean approve; } diff --git a/travelution/src/main/java/com/example/travelution/request/ValidateSubscriptionReq.java b/travelution/src/main/java/com/example/travelution/request/ValidateSubscriptionReq.java index aaa8d00..061bc65 100644 --- a/travelution/src/main/java/com/example/travelution/request/ValidateSubscriptionReq.java +++ b/travelution/src/main/java/com/example/travelution/request/ValidateSubscriptionReq.java @@ -1,5 +1,5 @@ package com.example.travelution.request; -public class ValidateSubscriptionReq { +public class ValidateSubscriptionReq extends Request{ public int subscriberId; } diff --git a/travelution/src/main/java/com/example/travelution/response/Response.java b/travelution/src/main/java/com/example/travelution/response/Response.java index 289ddb7..149b2d8 100644 --- a/travelution/src/main/java/com/example/travelution/response/Response.java +++ b/travelution/src/main/java/com/example/travelution/response/Response.java @@ -5,6 +5,9 @@ public class Response { public boolean success; public String message; + public Response() { + } + public Response(boolean success, String message) { this.success = success; this.message = message; diff --git a/travelution/src/main/java/com/example/travelution/response/SubscriptionApprovalResp.java b/travelution/src/main/java/com/example/travelution/response/SubscriptionApprovalResp.java index 9c71bcf..f48f93f 100644 --- a/travelution/src/main/java/com/example/travelution/response/SubscriptionApprovalResp.java +++ b/travelution/src/main/java/com/example/travelution/response/SubscriptionApprovalResp.java @@ -5,6 +5,9 @@ public class SubscriptionApprovalResp extends Response{ public Integer subscriberId; public String status; + public SubscriptionApprovalResp() { + super(); + } public SubscriptionApprovalResp(boolean success, String message, Integer subscriberId, String status) { super(success, message); this.subscriberId = subscriberId; diff --git a/travelution/src/main/java/com/example/travelution/response/SubscriptionListResp.java b/travelution/src/main/java/com/example/travelution/response/SubscriptionListResp.java index f2b2f04..b43eeda 100644 --- a/travelution/src/main/java/com/example/travelution/response/SubscriptionListResp.java +++ b/travelution/src/main/java/com/example/travelution/response/SubscriptionListResp.java @@ -5,6 +5,9 @@ import java.util.List; public class SubscriptionListResp extends Response{ public SubscriptionListWrapper list; + public SubscriptionListResp() { + super(); + } public SubscriptionListResp(boolean success, String message, List<Subscriber> list) { super(success, message); this.list = new SubscriptionListWrapper(list); diff --git a/travelution/src/main/java/com/example/travelution/response/SubscriptionListWrapper.java b/travelution/src/main/java/com/example/travelution/response/SubscriptionListWrapper.java index 6ba9dbb..422f1f7 100644 --- a/travelution/src/main/java/com/example/travelution/response/SubscriptionListWrapper.java +++ b/travelution/src/main/java/com/example/travelution/response/SubscriptionListWrapper.java @@ -4,6 +4,9 @@ import java.util.List; public class SubscriptionListWrapper { public List<Subscriber> elements; + public SubscriptionListWrapper(){ + + } public SubscriptionListWrapper(List<Subscriber> elements) { this.elements = elements; } diff --git a/travelution/src/main/java/com/example/travelution/response/SubscriptionResp.java b/travelution/src/main/java/com/example/travelution/response/SubscriptionResp.java index b5a0505..ae5d7be 100644 --- a/travelution/src/main/java/com/example/travelution/response/SubscriptionResp.java +++ b/travelution/src/main/java/com/example/travelution/response/SubscriptionResp.java @@ -5,6 +5,9 @@ public class SubscriptionResp extends Response{ public Integer subscriberId; public String status; + public SubscriptionResp() { + super(); + } public SubscriptionResp(boolean success, String message, Integer subscriberId, String status) { super(success, message); this.subscriberId = subscriberId; diff --git a/travelution/src/main/java/com/example/travelution/response/ValidateSubscriptionResp.java b/travelution/src/main/java/com/example/travelution/response/ValidateSubscriptionResp.java index 95a57ee..ca0cf85 100644 --- a/travelution/src/main/java/com/example/travelution/response/ValidateSubscriptionResp.java +++ b/travelution/src/main/java/com/example/travelution/response/ValidateSubscriptionResp.java @@ -5,6 +5,9 @@ public class ValidateSubscriptionResp extends Response{ public Integer subscriberId; public Boolean subscribed; + public ValidateSubscriptionResp(){ + super(); + } public ValidateSubscriptionResp(boolean success, String message, Integer subscriberId, Boolean subscribed) { super(success, message); this.subscriberId = subscriberId; -- GitLab