Merge pull request #19 from RohitAwate/state-maintenance-improvements

Improvements to application state maintenance logic
This commit is contained in:
Rohit Awate 2018-07-01 12:23:04 +05:30 committed by GitHub
commit e1e282c08b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 541 additions and 413 deletions

View file

@ -18,17 +18,16 @@ package com.rohitawate.everest.controllers;
import com.rohitawate.everest.controllers.codearea.EverestCodeArea;
import com.rohitawate.everest.controllers.codearea.EverestCodeArea.HighlightMode;
import com.rohitawate.everest.controllers.state.DashboardState;
import com.rohitawate.everest.controllers.state.FieldState;
import com.rohitawate.everest.misc.Services;
import com.rohitawate.everest.misc.ThemeManager;
import com.rohitawate.everest.models.DashboardState;
import com.rohitawate.everest.models.requests.DataDispatchRequest;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
@ -39,7 +38,6 @@ import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.ResourceBundle;
/*
@ -48,8 +46,6 @@ import java.util.ResourceBundle;
URL encoded and Form tabs have special FXMLs.
*/
public class BodyTabController implements Initializable {
@FXML
private TabPane bodyTabPane;
@FXML
ComboBox<String> rawInputTypeBox;
@FXML
@ -107,121 +103,98 @@ public class BodyTabController implements Initializable {
}
}
/**
* Returns a EverestRequest object initialized with the request body.
*/
public DataDispatchRequest getBasicRequest(String requestType) {
DataDispatchRequest request = new DataDispatchRequest(requestType);
// Raw and binary types get saved in Body.
// Form and URL encoded types use tuple objects
if (rawTab.isSelected()) {
String contentType;
switch (rawInputTypeBox.getValue()) {
case "PLAIN TEXT":
contentType = MediaType.TEXT_PLAIN;
break;
case "JSON":
contentType = MediaType.APPLICATION_JSON;
break;
case "XML":
contentType = MediaType.APPLICATION_XML;
break;
case "HTML":
contentType = MediaType.TEXT_HTML;
break;
default:
contentType = MediaType.TEXT_PLAIN;
}
request.setContentType(contentType);
request.setBody(rawInputArea.getText());
} else if (formTab.isSelected()) {
request.setStringTuples(formDataTabController.getStringTuples());
request.setFileTuples(formDataTabController.getFileTuples());
request.setContentType(MediaType.MULTIPART_FORM_DATA);
} else if (binaryTab.isSelected()) {
request.setBody(filePathField.getText());
request.setContentType(MediaType.APPLICATION_OCTET_STREAM);
} else if (urlTab.isSelected()) {
request.setStringTuples(urlTabController.getStringTuples());
request.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
}
return request;
}
@FXML
private void browseFile() {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Choose a binary file to add to request...");
Window dashboardWindow = filePathField.getScene().getWindow();
String filePath;
try {
filePath = fileChooser.showOpenDialog(dashboardWindow).getAbsolutePath();
} catch (NullPointerException NPE) {
filePath = "";
}
filePathField.setText(filePath);
}
public void setState(DashboardState dashboardState) {
try {
switch (dashboardState.getContentType()) {
case MediaType.TEXT_PLAIN:
setRawTab(dashboardState, "PLAIN TEXT");
break;
case MediaType.APPLICATION_JSON:
setRawTab(dashboardState, "JSON");
break;
case MediaType.APPLICATION_XML:
setRawTab(dashboardState, "XML");
break;
case MediaType.TEXT_HTML:
setRawTab(dashboardState, "HTML");
break;
case MediaType.MULTIPART_FORM_DATA:
// For file tuples
for (Map.Entry entry : dashboardState.getFileTuples().entrySet())
formDataTabController.addFileField(entry.getKey().toString(), entry.getValue().toString());
public DashboardState getState() {
DashboardState state = new DashboardState();
// For string tuples
for (Map.Entry entry : dashboardState.getStringTuples().entrySet())
formDataTabController.addStringField(entry.getKey().toString(), entry.getValue().toString());
bodyTabPane.getSelectionModel().select(formTab);
state.rawBodyType = rawInputTypeBox.getValue();
state.rawBody = rawInputArea.getText();
state.urlStringTuples = urlTabController.getFieldStates();
state.formStringTuples = formDataTabController.getStringFieldStates();
state.formFileTuples = formDataTabController.getFileFieldStates();
state.binaryFilePath = filePathField.getText();
if (rawTab.isSelected()) {
switch (rawInputTypeBox.getValue()) {
case "JSON":
state.contentType = MediaType.APPLICATION_JSON;
break;
case MediaType.APPLICATION_OCTET_STREAM:
filePathField.setText(dashboardState.getBody());
bodyTabPane.getSelectionModel().select(binaryTab);
case "XML":
state.contentType = MediaType.APPLICATION_XML;
break;
case MediaType.APPLICATION_FORM_URLENCODED:
for (Map.Entry entry : dashboardState.getStringTuples().entrySet())
urlTabController.addField(entry.getKey().toString(), entry.getValue().toString());
bodyTabPane.getSelectionModel().select(urlTab);
case "HTML":
state.contentType = MediaType.TEXT_HTML;
break;
default:
state.contentType = MediaType.TEXT_PLAIN;
}
} catch (NullPointerException NPE) {
Services.loggingService.logInfo("Dashboard loaded with blank request body.", LocalDateTime.now());
} else if (formTab.isSelected()) {
state.contentType = MediaType.MULTIPART_FORM_DATA;
} else if (urlTab.isSelected()) {
state.contentType = MediaType.APPLICATION_FORM_URLENCODED;
} else {
state.contentType = MediaType.APPLICATION_OCTET_STREAM;
}
return state;
}
private void setRawTab(DashboardState dashboardState, String contentType) {
public void setState(DashboardState state) {
// Adding URL tab's tuples
if (state.urlStringTuples != null)
for (FieldState fieldState : state.urlStringTuples)
urlTabController.addField(fieldState);
// Adding Form tab's string tuples
if (state.formStringTuples != null)
for (FieldState fieldState : state.formStringTuples)
formDataTabController.addStringField(fieldState);
// Adding Form tab's file tuples
if (state.formFileTuples != null)
for (FieldState fieldState : state.formFileTuples)
formDataTabController.addFileField(fieldState);
setRawTab(state);
filePathField.setText(state.binaryFilePath);
}
private void setRawTab(DashboardState state) {
HighlightMode mode;
switch (contentType) {
case MediaType.APPLICATION_JSON:
mode = HighlightMode.JSON;
break;
case MediaType.APPLICATION_XML:
mode = HighlightMode.XML;
break;
case MediaType.TEXT_HTML:
mode = HighlightMode.HTML;
break;
default:
mode = HighlightMode.PLAIN;
if (state.rawBodyType != null && state.rawBody != null) {
switch (state.rawBodyType) {
case "JSON":
mode = HighlightMode.JSON;
break;
case "XML":
mode = HighlightMode.XML;
break;
case "HTML":
mode = HighlightMode.HTML;
break;
default:
mode = HighlightMode.PLAIN;
}
rawInputArea.setText(state.rawBody, mode);
} else {
rawInputArea.setText("", HighlightMode.PLAIN);
}
rawInputArea.setText(dashboardState.getBody(), mode);
rawInputTypeBox.getSelectionModel().select(contentType);
bodyTabPane.getSelectionModel().select(rawTab);
}
}

View file

@ -21,12 +21,13 @@ import com.jfoenix.controls.JFXProgressBar;
import com.jfoenix.controls.JFXSnackbar;
import com.rohitawate.everest.controllers.codearea.EverestCodeArea;
import com.rohitawate.everest.controllers.codearea.EverestCodeArea.HighlightMode;
import com.rohitawate.everest.controllers.state.DashboardState;
import com.rohitawate.everest.controllers.state.FieldState;
import com.rohitawate.everest.exceptions.RedirectException;
import com.rohitawate.everest.exceptions.UnreliableResponseException;
import com.rohitawate.everest.misc.EverestUtilities;
import com.rohitawate.everest.misc.Services;
import com.rohitawate.everest.misc.ThemeManager;
import com.rohitawate.everest.models.DashboardState;
import com.rohitawate.everest.models.requests.DELETERequest;
import com.rohitawate.everest.models.requests.DataDispatchRequest;
import com.rohitawate.everest.models.requests.GETRequest;
@ -59,7 +60,6 @@ import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.ResourceBundle;
public class DashboardController implements Initializable {
@ -114,14 +114,14 @@ public class DashboardController implements Initializable {
headerTabController = headerTabLoader.getController();
headersTab.setContent(headerTabContent);
// Loading the body tab
// Loading the rawBody tab
FXMLLoader bodyTabLoader = new FXMLLoader(getClass().getResource("/fxml/homewindow/BodyTab.fxml"));
Parent bodyTabContent = bodyTabLoader.load();
ThemeManager.setTheme(bodyTabContent);
bodyTabController = bodyTabLoader.getController();
bodyTab.setContent(bodyTabContent);
} catch (IOException e) {
Services.loggingService.logSevere("Could not load headers/body tabs.", e, LocalDateTime.now());
Services.loggingService.logSevere("Could not load headers/rawBody tabs.", e, LocalDateTime.now());
}
snackbar = new JFXSnackbar(dashboard);
@ -154,7 +154,7 @@ public class DashboardController implements Initializable {
responseArea.selectAll();
responseArea.copy();
responseArea.deselect();
snackbar.show("Response body copied to clipboard.", 5000);
snackbar.show("Response rawBody copied to clipboard.", 5000);
});
responseTypeBox.getItems().addAll("JSON", "XML", "HTML", "PLAIN TEXT");
@ -233,7 +233,7 @@ public class DashboardController implements Initializable {
getRequest = new GETRequest();
getRequest.setTarget(address);
getRequest.setHeaders(headerTabController.getSelectedHeaders());
getRequest.setHeaders(headerTabController.getHeaders());
requestManager = Services.pool.get();
requestManager.setRequest(getRequest);
@ -250,7 +250,7 @@ public class DashboardController implements Initializable {
dataRequest.setRequestType(httpMethodBox.getValue());
dataRequest.setTarget(address);
dataRequest.setHeaders(headerTabController.getSelectedHeaders());
dataRequest.setHeaders(headerTabController.getHeaders());
if (bodyTabController.rawTab.isSelected()) {
String contentType;
@ -296,7 +296,7 @@ public class DashboardController implements Initializable {
deleteRequest = new DELETERequest();
deleteRequest.setTarget(address);
deleteRequest.setHeaders(headerTabController.getSelectedHeaders());
deleteRequest.setHeaders(headerTabController.getHeaders());
requestManager = Services.pool.delete();
requestManager.setRequest(deleteRequest);
@ -354,7 +354,7 @@ public class DashboardController implements Initializable {
if (requestManager.getClass() == DataDispatchRequestManager.class) {
if (throwable.getCause() != null && throwable.getCause().getClass() == IllegalArgumentException.class) {
errorTitle.setText("Did you forget something?");
errorDetails.setText("Please specify at least one body part for your " + httpMethodBox.getValue() + " request.");
errorDetails.setText("Please specify at least one rawBody part for your " + httpMethodBox.getValue() + " request.");
} else if (throwable.getClass() == FileNotFoundException.class) {
errorTitle.setText("File(s) not found:");
errorDetails.setText(throwable.getMessage());
@ -434,7 +434,7 @@ public class DashboardController implements Initializable {
}
} else {
responseTypeBox.setValue("PLAIN");
responseArea.setText("No body found in the response.", HighlightMode.PLAIN);
responseArea.setText("No rawBody found in the response.", HighlightMode.PLAIN);
}
} catch (Exception e) {
snackbar.show("Response could not be parsed.", 5000);
@ -468,35 +468,41 @@ public class DashboardController implements Initializable {
}
}
private HashMap<String, String> getParams() {
if (params == null)
params = new HashMap<>();
/**
* @return List of the states of all the non-empty fields in the Params tab.
*/
public ArrayList<FieldState> getParamFieldStates() {
ArrayList<FieldState> states = new ArrayList<>();
params.clear();
for (StringKeyValueFieldController controller : paramsControllers)
if (controller.isChecked())
params.put(controller.getHeader().getKey(), controller.getHeader().getValue());
return params;
if (!controller.isKeyFieldEmpty() && !controller.isValueFieldEmpty())
states.add(controller.getState());
return states;
}
private void addParamField() {
addParamField("", "", null);
addParamField("", "", null, false);
}
private void addParamField(String key, String value) {
addParamField(key, value, null);
private void addParamField(FieldState state) {
addParamField(state.key, state.value, null, state.checked);
}
@FXML
private void addParamField(ActionEvent event) {
addParamField("", "", event);
addParamField("", "", event, false);
}
// Adds a new URL-parameter field
private void addParamField(String key, String value, ActionEvent event) {
/**
* Adds a new URL-parameter field
*/
private void addParamField(String key, String value, ActionEvent event, boolean checked) {
/*
Re-uses previous field if it is empty,
else loads a new one.
Re-uses previous field if it is empty, else loads a new one.
A value of null for the 'event' parameter indicates that the method call
came from code and not from the user. This call is made while recovering
the application state.
*/
if (paramsControllers.size() > 0 && event == null) {
StringKeyValueFieldController previousController = paramsControllers.get(paramsControllers.size() - 1);
@ -515,6 +521,7 @@ public class DashboardController implements Initializable {
StringKeyValueFieldController controller = loader.getController();
controller.setKeyField(key);
controller.setValueField(value);
controller.setChecked(checked);
paramsControllers.add(controller);
paramsCountProperty.set(paramsCountProperty.get() + 1);
controller.deleteButton.visibleProperty().bind(Bindings.greaterThan(paramsCountProperty, 1));
@ -530,9 +537,7 @@ public class DashboardController implements Initializable {
}
/**
* Returns the current state of the Dashboard
*
* @return DashboardState - Current state of the Dashboard
* @return Current state of the Dashboard.
*/
public DashboardState getState() {
DashboardState dashboardState;
@ -540,22 +545,17 @@ public class DashboardController implements Initializable {
case "POST":
case "PUT":
case "PATCH":
dashboardState = new DashboardState(bodyTabController.getBasicRequest(httpMethodBox.getValue()));
dashboardState.setHeaders(headerTabController.getSelectedHeaders());
dashboardState = bodyTabController.getState();
break;
default:
// For GET, DELETE requests
dashboardState = new DashboardState();
}
try {
dashboardState.setTarget(addressField.getText());
} catch (MalformedURLException e) {
Services.loggingService.logInfo("Dashboard state was saved with an invalid URL.", LocalDateTime.now());
}
dashboardState.setHttpMethod(httpMethodBox.getValue());
dashboardState.setHeaders(headerTabController.getSelectedHeaders());
dashboardState.setParams(getParams());
dashboardState.target = addressField.getText();
dashboardState.httpMethod = httpMethodBox.getValue();
dashboardState.headers = headerTabController.getFieldStates();
dashboardState.params = getParamFieldStates();
return dashboardState;
}
@ -563,23 +563,34 @@ public class DashboardController implements Initializable {
/**
* Sets the Dashboard to the given application state.
*
* @param dashboardState - State of the dashboard
* @param state - State of the dashboard
*/
public void setState(DashboardState dashboardState) {
if (dashboardState.getTarget() != null)
addressField.setText(dashboardState.getTarget().toString());
public void setState(DashboardState state) {
boolean validMethod = false;
for (String method : httpMethods) {
if (state.httpMethod.equals(method))
validMethod = true;
}
httpMethodBox.getSelectionModel().select(dashboardState.getHttpMethod());
if (!validMethod) {
Services.loggingService.logInfo("Application state file was tampered with. State could not be recovered.", LocalDateTime.now());
return;
}
if (dashboardState.getHeaders() != null)
for (Entry entry : dashboardState.getHeaders().entrySet())
headerTabController.addHeader(entry.getKey().toString(), entry.getValue().toString());
httpMethodBox.setValue(state.httpMethod);
if (dashboardState.getParams() != null)
for (Entry entry : dashboardState.getParams().entrySet())
addParamField(entry.getKey().toString(), entry.getValue().toString());
if (state.target != null)
addressField.setText(state.target);
if (state.headers != null)
for (FieldState fieldState : state.headers)
headerTabController.addHeader(fieldState);
if (state.params != null)
for (FieldState fieldState : state.params)
addParamField(fieldState);
if (!(httpMethodBox.getValue().equals("GET") || httpMethodBox.getValue().equals("DELETE")))
bodyTabController.setState(dashboardState);
bodyTabController.setState(state);
}
}

View file

@ -18,6 +18,7 @@ package com.rohitawate.everest.controllers;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXCheckBox;
import com.rohitawate.everest.controllers.state.FieldState;
import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
@ -108,4 +109,12 @@ public class FileKeyValueFieldController implements Initializable {
public boolean isFileValueFieldEmpty() {
return fileValueField.getText().isEmpty();
}
public FieldState getState() {
return new FieldState(fileKeyField.getText(), fileValueField.getText(), checkBox.isSelected());
}
public void setChecked(boolean checked) {
checkBox.setSelected(checked);
}
}

View file

@ -16,6 +16,7 @@
package com.rohitawate.everest.controllers;
import com.rohitawate.everest.controllers.state.FieldState;
import com.rohitawate.everest.misc.Services;
import com.rohitawate.everest.misc.ThemeManager;
import javafx.beans.binding.Bindings;
@ -59,22 +60,26 @@ public class FormDataTabController implements Initializable {
addStringField();
}
public void addFileField(FieldState state) {
addFileField(state.key, state.value, null, state.checked);
}
@FXML
private void addFileField(ActionEvent event) {
addFileField("", "", event);
addFileField("", "", event, false);
}
private void addFileField() {
addFileField("", "", null);
addFileField("", "", null, false);
}
public void addFileField(String key, String value) {
addFileField(key, value, null);
}
private void addFileField(String key, String value, ActionEvent event) {
//Re-uses previous field if it is empty else loads a new one.
private void addFileField(String key, String value, ActionEvent event, boolean checked) {
/*
Re-uses previous field if it is empty, else loads a new one.
A value of null for the 'event' parameter indicates that the method call
came from code and not from the user. This call is made while recovering
the application state.
*/
if (fileControllers.size() > 0 && event == null) {
FileKeyValueFieldController previousController = fileControllers.get(fileControllers.size() - 1);
@ -93,6 +98,7 @@ public class FormDataTabController implements Initializable {
FileKeyValueFieldController controller = loader.getController();
controller.setFileKeyField(key);
controller.setFileValueField(value);
controller.setChecked(checked);
fileControllers.add(controller);
fileControllersCount.set(fileControllersCount.get() + 1);
controller.deleteButton.visibleProperty().bind(Bindings.greaterThan(fileControllersCount, 1));
@ -103,27 +109,29 @@ public class FormDataTabController implements Initializable {
});
fieldsBox.getChildren().add(fileField);
} catch (IOException e) {
Services.loggingService.logSevere("Could not load file field.", e, LocalDateTime.now());
Services.loggingService.logSevere("Could not add file field.", e, LocalDateTime.now());
}
}
public void addStringField(FieldState state) {
addStringField(state.key, state.value, null, state.checked);
}
@FXML
private void addStringField(ActionEvent event) {
addStringField("", "", event);
addStringField("", "", event, false);
}
private void addStringField() {
addStringField("", "", null);
addStringField("", "", null, false);
}
public void addStringField(String key, String value) {
addStringField(key, value, null);
}
private void addStringField(String key, String value, ActionEvent event) {
private void addStringField(String key, String value, ActionEvent event, boolean checked) {
/*
Re-uses previous field if it is empty,
else loads a new one.
Re-uses previous field if it is empty, else loads a new one.
A value of null for the 'event' parameter indicates that the method call
came from code and not from the user. This call is made while recovering
the application state.
*/
if (stringControllers.size() > 0 && event == null) {
StringKeyValueFieldController previousController = stringControllers.get(stringControllers.size() - 1);
@ -142,6 +150,7 @@ public class FormDataTabController implements Initializable {
StringKeyValueFieldController controller = loader.getController();
controller.setKeyField(key);
controller.setValueField(value);
controller.setChecked(checked);
stringControllers.add(controller);
stringControllersCount.set(stringControllersCount.get() + 1);
controller.deleteButton.visibleProperty().bind(Bindings.greaterThan(stringControllersCount, 1));
@ -152,10 +161,13 @@ public class FormDataTabController implements Initializable {
});
fieldsBox.getChildren().add(stringField);
} catch (IOException e) {
Services.loggingService.logSevere("Could not load string field.", e, LocalDateTime.now());
Services.loggingService.logSevere("Could not add string field.", e, LocalDateTime.now());
}
}
/**
* @return Map of selected string tuples from multipart-form tab
*/
public HashMap<String, String> getStringTuples() {
if (stringMap == null)
stringMap = new HashMap<>();
@ -165,9 +177,13 @@ public class FormDataTabController implements Initializable {
if (controller.isChecked())
stringMap.put(controller.getHeader().getKey(), controller.getHeader().getValue());
}
return stringMap;
}
/**
* @return Map of selected file tuples from multipart-form tab
*/
public HashMap<String, String> getFileTuples() {
if (fileMap == null)
fileMap = new HashMap<>();
@ -179,4 +195,32 @@ public class FormDataTabController implements Initializable {
}
return fileMap;
}
/**
* @return List of the states of all the non-empty string fields in the Form data tab.
*/
public ArrayList<FieldState> getStringFieldStates() {
ArrayList<FieldState> states = new ArrayList<>();
for (StringKeyValueFieldController controller : stringControllers)
if (!controller.isKeyFieldEmpty() && !controller.isValueFieldEmpty())
states.add(controller.getState());
return states;
}
/**
* @return List of the states of all the non-empty file fields in the Form data tab.
*/
public ArrayList<FieldState> getFileFieldStates() {
ArrayList<FieldState> states = new ArrayList<>();
for (FileKeyValueFieldController controller : fileControllers)
if (!controller.isFileKeyFieldEmpty() && !controller.isFileValueFieldEmpty())
states.add(controller.getState());
return states;
}
}

View file

@ -16,6 +16,7 @@
package com.rohitawate.everest.controllers;
import com.rohitawate.everest.controllers.state.FieldState;
import com.rohitawate.everest.misc.Services;
import com.rohitawate.everest.misc.ThemeManager;
import javafx.beans.binding.Bindings;
@ -52,23 +53,25 @@ public class HeaderTabController implements Initializable {
addHeader();
}
public void addHeader(String key, String value) {
addHeader(key, value, null);
public void addHeader(FieldState state) {
addHeader(state.key, state.value, null, state.checked);
}
private void addHeader() {
addHeader("", "", null);
addHeader("", "", null, false);
}
@FXML
private void addHeader(ActionEvent event) {
addHeader("", "", event);
addHeader("", "", event, false);
}
private void addHeader(String key, String value, ActionEvent event) {
private void addHeader(String key, String value, ActionEvent event, boolean checked) {
/*
Re-uses previous field if it is empty,
else loads a new one.
Re-uses previous field if it is empty, else loads a new one.
A value of null for the 'event' parameter indicates that the method call
came from code and not from the user. This call is made while recovering
the application state.
*/
if (controllers.size() > 0 && event == null) {
StringKeyValueFieldController previousController = controllers.get(controllers.size() - 1);
@ -88,6 +91,7 @@ public class HeaderTabController implements Initializable {
StringKeyValueFieldController controller = loader.getController();
controller.setKeyField(key);
controller.setValueField(value);
controller.setChecked(checked);
controllers.add(controller);
controllersCount.set(controllersCount.get() + 1);
controller.deleteButton.visibleProperty().bind(Bindings.greaterThan(controllersCount, 1));
@ -98,14 +102,14 @@ public class HeaderTabController implements Initializable {
});
headersBox.getChildren().add(headerField);
} catch (IOException e) {
Services.loggingService.logSevere("Could not string field.", e, LocalDateTime.now());
Services.loggingService.logSevere("Could not add string field.", e, LocalDateTime.now());
}
}
/**
* Returns a map of the selected headers.
* @return Map of the selected headers.
*/
public HashMap<String, String> getSelectedHeaders() {
public HashMap<String, String> getHeaders() {
if (headers == null)
headers = new HashMap<>();
@ -114,6 +118,20 @@ public class HeaderTabController implements Initializable {
if (controller.isChecked())
headers.put(controller.getHeader().getKey(), controller.getHeader().getValue());
}
return headers;
}
/**
* Return a list of the state of all the non-empty fields in the Headers tab.
*/
public ArrayList<FieldState> getFieldStates() {
ArrayList<FieldState> states = new ArrayList<>();
for (StringKeyValueFieldController controller : controllers)
if (!controller.isKeyFieldEmpty() && !controller.isValueFieldEmpty())
states.add(controller.getState());
return states;
}
}

View file

@ -16,15 +16,18 @@
package com.rohitawate.everest.controllers;
import com.rohitawate.everest.models.DashboardState;
import com.rohitawate.everest.controllers.state.DashboardState;
import com.rohitawate.everest.controllers.state.FieldState;
import com.rohitawate.everest.misc.Services;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javax.ws.rs.core.MediaType;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import java.time.LocalDateTime;
import java.util.ResourceBundle;
public class HistoryItemController implements Initializable {
@ -33,35 +36,21 @@ public class HistoryItemController implements Initializable {
@FXML
private Tooltip tooltip;
private DashboardState dashboardState;
public void setRequestType(String requestType) {
this.requestType.setText(requestType);
}
public void setAddress(String address) {
this.address.setText(address);
}
public String getRequestType() {
return requestType.getText();
}
public String getAddress() {
return address.getText();
}
private DashboardState state;
@Override
public void initialize(URL location, ResourceBundle resources) {
tooltip.textProperty().bind(address.textProperty());
}
public DashboardState getDashboardState() {
return dashboardState;
public DashboardState getState() {
return state;
}
public void setDashboardState(DashboardState dashboardState) {
this.dashboardState = dashboardState;
public void setState(DashboardState state) {
this.state = state;
this.requestType.setText(state.httpMethod);
this.address.setText(state.target);
}
public int getRelativityIndex(String searchString) {
@ -69,70 +58,76 @@ public class HistoryItemController implements Initializable {
String comparisonString;
// Checks if matches with target
comparisonString = dashboardState.getTarget().toString().toLowerCase();
comparisonString = state.target.toLowerCase();
if (comparisonString.contains(searchString))
return 10;
// Checks if matches with target's hostname
comparisonString = dashboardState.getTarget().getHost().toLowerCase();
if (comparisonString.contains(searchString))
return 10;
try {
URL url = new URL(state.target);
// Checks if matches with target's path
comparisonString = dashboardState.getTarget().getPath().toLowerCase();
if (comparisonString.contains(searchString))
return 9;
// Checks if matches with target's hostname
comparisonString = url.getHost().toLowerCase();
if (comparisonString.contains(searchString))
return 10;
// Checks if matches with target's path
comparisonString = url.getPath().toLowerCase();
if (comparisonString.contains(searchString))
return 9;
} catch (MalformedURLException e) {
Services.loggingService.logInfo("Failed to parse URL while calculating relativity index.", LocalDateTime.now());
}
// Checks if matches with HTTP method
comparisonString = dashboardState.getHttpMethod().toLowerCase();
comparisonString = state.httpMethod.toLowerCase();
if (comparisonString.contains(searchString))
return 7;
// Checks for a match in the params
for (Map.Entry param : dashboardState.getParams().entrySet()) {
if (param.getKey().toString().toLowerCase().contains(searchString) ||
param.getKey().toString().toLowerCase().contains(searchString))
for (FieldState state : state.params) {
if (state.key.toLowerCase().contains(searchString) ||
state.value.toLowerCase().contains(searchString))
return 5;
}
// Checks for a match in the headers
for (Map.Entry header : dashboardState.getHeaders().entrySet()) {
if (header.getKey().toString().toLowerCase().contains(searchString) ||
header.getValue().toString().toLowerCase().contains(searchString))
for (FieldState state : state.headers) {
if (state.key.toLowerCase().contains(searchString) ||
state.value.toLowerCase().contains(searchString))
return 6;
}
if (dashboardState.getHttpMethod().equals("POST") || dashboardState.getHttpMethod().equals("PUT")) {
switch (dashboardState.getContentType()) {
if (state.httpMethod.equals("POST") || state.httpMethod.equals("PUT")) {
switch (state.contentType) {
case MediaType.TEXT_PLAIN:
case MediaType.APPLICATION_JSON:
case MediaType.APPLICATION_XML:
case MediaType.TEXT_HTML:
case MediaType.APPLICATION_OCTET_STREAM:
// Checks for match in body of the request
comparisonString = dashboardState.getBody().toLowerCase();
// Checks for match in rawBody of the request
comparisonString = state.rawBody.toLowerCase();
if (comparisonString.contains(searchString))
return 8;
break;
case MediaType.APPLICATION_FORM_URLENCODED:
// Checks for match in string tuples
for (Map.Entry tuple : dashboardState.getStringTuples().entrySet()) {
if (tuple.getKey().toString().toLowerCase().contains(searchString) ||
tuple.getValue().toString().toLowerCase().contains(searchString))
for (FieldState state : state.urlStringTuples) {
if (state.key.toLowerCase().contains(searchString) ||
state.value.toLowerCase().contains(searchString))
return 8;
}
break;
case MediaType.MULTIPART_FORM_DATA:
// Checks for match in string and file tuples
for (Map.Entry tuple : dashboardState.getStringTuples().entrySet()) {
if (tuple.getKey().toString().toLowerCase().contains(searchString) ||
tuple.getValue().toString().toLowerCase().contains(searchString))
for (FieldState state : state.formStringTuples) {
if (state.key.toLowerCase().contains(searchString) ||
state.value.toLowerCase().contains(searchString))
return 8;
}
for (Map.Entry tuple : dashboardState.getFileTuples().entrySet()) {
if (tuple.getKey().toString().toLowerCase().contains(searchString) ||
tuple.getValue().toString().toLowerCase().contains(searchString))
for (FieldState state : state.formFileTuples) {
if (state.key.toLowerCase().contains(searchString) ||
state.value.toLowerCase().contains(searchString))
return 8;
}
break;

View file

@ -16,11 +16,13 @@
package com.rohitawate.everest.controllers;
import com.fasterxml.jackson.core.type.TypeReference;
import com.jfoenix.controls.JFXButton;
import com.rohitawate.everest.controllers.state.DashboardState;
import com.rohitawate.everest.misc.EverestUtilities;
import com.rohitawate.everest.misc.KeyMap;
import com.rohitawate.everest.misc.Services;
import com.rohitawate.everest.misc.ThemeManager;
import com.rohitawate.everest.models.DashboardState;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.StringProperty;
@ -39,7 +41,8 @@ import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.io.*;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.*;
@ -92,7 +95,7 @@ public class HomeWindowController implements Initializable {
if (searchResults.size() != 0) {
for (HistoryItemController controller : searchResults) {
addSearchItem(controller.getDashboardState());
addSearchItem(controller.getState());
}
} else {
searchFailedLayer.setVisible(true);
@ -243,39 +246,36 @@ public class HomeWindowController implements Initializable {
}
private void saveState() {
List<DashboardState> dashboardStates = new ArrayList<>();
ArrayList<DashboardState> dashboardStates = new ArrayList<>();
// Get the states of all the tabs
for (DashboardController controller : tabControllerMap.values())
dashboardStates.add(controller.getState());
try {
File configFolder = new File("Everest/config/");
if (!configFolder.exists())
configFolder.mkdirs();
OutputStream fileStream = new FileOutputStream("Everest/config/everest.state");
ObjectOutputStream objectStream = new ObjectOutputStream(fileStream);
objectStream.writeObject(dashboardStates);
objectStream.close();
fileStream.close();
Services.loggingService.logInfo("Application state was saved successfully.", LocalDateTime.now());
File stateFile = new File("Everest/config/state.json");
EverestUtilities.jsonMapper.writeValue(stateFile, dashboardStates);
Services.loggingService.logInfo("Application state saved.", LocalDateTime.now());
} catch (IOException e) {
Services.loggingService.logSevere("Failed to save the application's state.", e, LocalDateTime.now());
Services.loggingService.logSevere("Failed to save application state.", e, LocalDateTime.now());
}
}
private void recoverState() {
try {
InputStream fileStream = new FileInputStream("Everest/config/everest.state");
ObjectInputStream objectStream = new ObjectInputStream(fileStream);
File stateFile = new File("Everest/config/state.json");
Services.loggingService.logInfo("Application state file found.", LocalDateTime.now());
if (!stateFile.exists()) {
Services.loggingService.logInfo("Application state file not found. Loading default state.", LocalDateTime.now());
addTab();
return;
}
List<DashboardState> dashboardStates = (List<DashboardState>) objectStream.readObject();
objectStream.close();
fileStream.close();
ArrayList<DashboardState> dashboardStates = EverestUtilities.jsonMapper
.reader()
.forType(new TypeReference<ArrayList<DashboardState>>() {
})
.readValue(stateFile);
if (dashboardStates.size() > 0) {
for (DashboardState dashboardState : dashboardStates)
@ -283,15 +283,12 @@ public class HomeWindowController implements Initializable {
} else {
addTab();
}
} catch (FileNotFoundException e) {
Services.loggingService.logWarning("Application state file not found. Loading default state.", e, LocalDateTime.now());
addTab();
} catch (IOException | ClassNotFoundException e) {
Services.loggingService.logWarning("Application state file is possibly corrupted. Could not recover the state.\nLoading default state.", e, LocalDateTime.now());
addTab();
} catch (IOException e) {
Services.loggingService.logWarning("Application state file is possibly corrupted. State recovery failed. Loading default state.", e, LocalDateTime.now());
} finally {
Services.loggingService.logInfo("Application loaded.", LocalDateTime.now());
}
}
public void addHistoryItem(DashboardState state) {
@ -311,11 +308,7 @@ public class HomeWindowController implements Initializable {
Parent historyItem = loader.load();
controller = loader.getController();
controller.setRequestType(state.getHttpMethod());
controller.setAddress(state.getTarget().toString());
controller.setDashboardState(state);
controller.setState(state);
if (appendToStart)
layer.getChildren().add(0, historyItem);

View file

@ -18,6 +18,7 @@ package com.rohitawate.everest.controllers;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXCheckBox;
import com.rohitawate.everest.controllers.state.FieldState;
import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
@ -91,4 +92,12 @@ public class StringKeyValueFieldController implements Initializable {
public boolean isValueFieldEmpty() {
return valueField.getText().isEmpty();
}
public FieldState getState() {
return new FieldState(keyField.getText(), valueField.getText(), checkBox.isSelected());
}
public void setChecked(boolean checked) {
checkBox.setSelected(checked);
}
}

View file

@ -16,6 +16,7 @@
package com.rohitawate.everest.controllers;
import com.rohitawate.everest.controllers.state.FieldState;
import com.rohitawate.everest.misc.Services;
import com.rohitawate.everest.misc.ThemeManager;
import javafx.beans.binding.Bindings;
@ -51,23 +52,26 @@ public class URLTabController implements Initializable {
addField();
}
private void addField() {
addField("", "", null);
public void addField(FieldState state) {
addField(state.key, state.value, null, state.checked);
}
public void addField(String key, String value) {
addField(key, value, null);
private void addField() {
addField("", "", null, false);
}
@FXML
private void addField(ActionEvent event) {
addField("", "", event);
addField("", "", event, false);
}
private void addField(String key, String value, ActionEvent event) {
private void addField(String key, String value, ActionEvent event, boolean checked) {
/*
Re-uses previous field if it is empty,
else loads a new one.
Re-uses previous field if it is empty, else loads a new one.
A value of null for the 'event' parameter indicates that the method call
came from code and not from the user. This call is made while recovering
the application state.
*/
if (controllers.size() > 0 && event == null) {
StringKeyValueFieldController previousController = controllers.get(controllers.size() - 1);
@ -87,6 +91,7 @@ public class URLTabController implements Initializable {
StringKeyValueFieldController controller = loader.getController();
controller.setKeyField(key);
controller.setValueField(value);
controller.setChecked(checked);
controllers.add(controller);
controllersCount.set(controllersCount.get() + 1);
controller.deleteButton.visibleProperty().bind(Bindings.greaterThan(controllersCount, 1));
@ -97,10 +102,13 @@ public class URLTabController implements Initializable {
});
fieldsBox.getChildren().add(stringField);
} catch (IOException e) {
Services.loggingService.logSevere("Could not load string field.", e, LocalDateTime.now());
Services.loggingService.logSevere("Could not add string field.", e, LocalDateTime.now());
}
}
/**
* @return Map of selected string tuples from URL-encoded tab.
*/
public HashMap<String, String> getStringTuples() {
if (tuples == null)
tuples = new HashMap<>();
@ -110,6 +118,21 @@ public class URLTabController implements Initializable {
if (controller.isChecked())
tuples.put(controller.getHeader().getKey(), controller.getHeader().getValue());
}
return tuples;
}
/**
* @return A list of the states of all the non-empty fields in the URL-encoded tab.
*/
public ArrayList<FieldState> getFieldStates() {
ArrayList<FieldState> states = new ArrayList<>();
for (StringKeyValueFieldController controller : controllers)
if (!controller.isKeyFieldEmpty() && !controller.isValueFieldEmpty())
states.add(controller.getState());
return states;
}
}

View file

@ -0,0 +1,46 @@
/*
* Copyright 2018 Rohit Awate.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.rohitawate.everest.controllers.state;
import java.util.ArrayList;
/**
* Convenience class to abstract the state of the application.
*/
public class DashboardState {
public String target;
public String httpMethod;
public ArrayList<FieldState> params;
public ArrayList<FieldState> headers;
// Determined from the active tab within the Body tab
public String contentType;
// Body and content-type of requests with raw bodies
public String rawBody;
public String rawBodyType;
// Tuples of URL-encoded requests
public ArrayList<FieldState> urlStringTuples;
// String and file tuples of multipart-form requests
public ArrayList<FieldState> formStringTuples;
public ArrayList<FieldState> formFileTuples;
// File path of application/octet-stream requests
public String binaryFilePath;
}

View file

@ -0,0 +1,51 @@
/*
* Copyright 2018 Rohit Awate.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.rohitawate.everest.controllers.state;
import java.util.Objects;
/**
* Convenience class to represent the state of StringKeyValueFieldController and FileKeyValueField for
* application state maintenance logic.
*/
public class FieldState {
public String key;
public String value;
public boolean checked;
public FieldState() {
this.key = null;
this.value = null;
this.checked = false;
}
public FieldState(String key, String value, boolean checked) {
this.key = key;
this.value = value;
this.checked = checked;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FieldState that = (FieldState) o;
return checked == that.checked &&
Objects.equals(key, that.key) &&
Objects.equals(value, that.value);
}
}

View file

@ -18,23 +18,21 @@ package com.rohitawate.everest.history;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rohitawate.everest.controllers.state.DashboardState;
import com.rohitawate.everest.controllers.state.FieldState;
import com.rohitawate.everest.misc.EverestUtilities;
import com.rohitawate.everest.misc.Services;
import com.rohitawate.everest.models.DashboardState;
import com.rohitawate.everest.settings.Settings;
import javax.ws.rs.core.MediaType;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.sql.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
public class HistoryManager {
private Connection conn;
@ -61,7 +59,7 @@ public class HistoryManager {
/**
* Creates and initializes the database with necessary tables if not already done.
*
* @throws IOException - If unable to establish a connection to the database.
* @throws IOException - If unable to establish a connection to the database.
* @throws SQLException - If invalid statement is executed on the database.
*/
private void initDatabase() throws IOException, SQLException {
@ -126,18 +124,14 @@ public class HistoryManager {
while (resultSet.next()) {
state = new DashboardState();
try {
state.setTarget(resultSet.getString("Target"));
} catch (MalformedURLException e) {
e.printStackTrace();
}
state.target = resultSet.getString("Target");
int requestID = resultSet.getInt("ID");
state.setHeaders(getRequestHeaders(requestID));
state.setParams(getTuples(requestID, "Param"));
state.setHttpMethod(resultSet.getString("Type"));
state.headers = getRequestHeaders(requestID);
state.params = getTuples(requestID, "Param");
state.httpMethod = resultSet.getString("Type");
if (!(state.getHttpMethod().equals("GET") || state.getHttpMethod().equals("DELETE"))) {
if (!(state.httpMethod.equals("GET") || state.httpMethod.equals("DELETE"))) {
// Retrieves request body ContentType for querying corresponding table
statement = conn.prepareStatement(EverestUtilities.trimString(queries.get("selectRequestContentType").toString()));
statement.setInt(1, requestID);
@ -148,7 +142,7 @@ public class HistoryManager {
if (RS.next())
contentType = RS.getString("ContentType");
state.setContentType(contentType);
state.contentType = contentType;
// Retrieves body from corresponding table
switch (contentType) {
@ -163,14 +157,14 @@ public class HistoryManager {
RS = statement.executeQuery();
if (RS.next())
state.setBody(RS.getString("Body"));
state.rawBody = RS.getString("Body");
break;
case MediaType.APPLICATION_FORM_URLENCODED:
state.setStringTuples(getTuples(requestID, "String"));
state.urlStringTuples = getTuples(requestID, "String");
break;
case MediaType.MULTIPART_FORM_DATA:
state.setStringTuples(getTuples(requestID, "String"));
state.setFileTuples(getTuples(requestID, "File"));
state.formStringTuples = getTuples(requestID, "String");
state.formFileTuples = getTuples(requestID, "File");
break;
}
}
@ -183,8 +177,8 @@ public class HistoryManager {
return history;
}
private HashMap<String, String> getRequestHeaders(int requestID) {
HashMap<String, String> headers = new HashMap<>();
private ArrayList<FieldState> getRequestHeaders(int requestID) {
ArrayList<FieldState> headers = new ArrayList<>();
try {
PreparedStatement statement =
@ -194,10 +188,12 @@ public class HistoryManager {
ResultSet RS = statement.executeQuery();
String key, value;
boolean checked;
while (RS.next()) {
key = RS.getString("Key");
value = RS.getString("Value");
headers.put(key, value);
checked = RS.getBoolean("Checked");
headers.add(new FieldState(key, value, checked));
}
} catch (SQLException e) {
Services.loggingService.logWarning("Database error.", e, LocalDateTime.now());
@ -210,11 +206,11 @@ public class HistoryManager {
* @param type Type of tuples needed ('String', 'File' or 'Param')
* @return tuples - Map of tuples of corresponding type
*/
private HashMap<String, String> getTuples(int requestID, String type) {
private ArrayList<FieldState> getTuples(int requestID, String type) {
if (!(type.equals("String") || type.equals("File") || type.equals("Param")))
return null;
HashMap<String, String> tuples = new HashMap<>();
ArrayList<FieldState> tuples = new ArrayList<>();
try {
PreparedStatement statement =
@ -225,14 +221,17 @@ public class HistoryManager {
ResultSet RS = statement.executeQuery();
String key, value;
boolean checked;
while (RS.next()) {
key = RS.getString("Key");
value = RS.getString("Value");
tuples.put(key, value);
checked = RS.getBoolean("Checked");
tuples.add(new FieldState(key, value, checked));
}
} catch (SQLException e) {
Services.loggingService.logWarning("Database error.", e, LocalDateTime.now());
}
return tuples;
}
@ -249,8 +248,8 @@ public class HistoryManager {
int lastRequestID = -1;
if (RS.next()) {
if (!(newState.getHttpMethod().equals(RS.getString("Type"))) ||
!(newState.getTarget().toString().equals(RS.getString("Target"))) ||
if (!(newState.httpMethod.equals(RS.getString("Type"))) ||
!(newState.target.equals(RS.getString("Target"))) ||
!(LocalDate.now().equals(LocalDate.parse(RS.getString("Date")))))
return false;
else
@ -261,20 +260,32 @@ public class HistoryManager {
if (lastRequestID == -1)
return false;
HashMap<String, String> map;
ArrayList<FieldState> states;
// Checks for new or modified headers
map = getRequestHeaders(lastRequestID);
if (!areMapsIdentical(map, newState.getHeaders()))
states = getRequestHeaders(lastRequestID);
if (!areListsEqual(states, newState.headers))
return false;
// Checks for new or modified params
map = getTuples(lastRequestID, "Param");
if (!areMapsIdentical(map, newState.getParams()))
states = getTuples(lastRequestID, "Param");
if (!areListsEqual(states, newState.params))
return false;
if (!(newState.getHttpMethod().equals("GET") || newState.getHttpMethod().equals("DELETE"))) {
switch (newState.getContentType()) {
if (!(newState.httpMethod.equals("GET") || newState.httpMethod.equals("DELETE"))) {
statement = conn.prepareStatement(EverestUtilities.trimString(queries.get("selectRequestContentType").toString()));
statement.setInt(1, lastRequestID);
RS = statement.executeQuery();
String previousContentType = "";
if (RS.next())
previousContentType = RS.getString("ContentType");
if (!newState.contentType.equals(previousContentType))
return false;
switch (newState.contentType) {
case MediaType.TEXT_PLAIN:
case MediaType.APPLICATION_JSON:
case MediaType.APPLICATION_XML:
@ -286,22 +297,22 @@ public class HistoryManager {
RS = statement.executeQuery();
if (RS.next())
if (!RS.getString("Body").equals(newState.getBody()))
if (!RS.getString("Body").equals(newState.rawBody))
return false;
break;
case MediaType.APPLICATION_FORM_URLENCODED:
// Checks for new or modified string tuples
map = getTuples(lastRequestID, "String");
return areMapsIdentical(map, newState.getStringTuples());
states = getTuples(lastRequestID, "String");
return areListsEqual(states, newState.urlStringTuples);
case MediaType.MULTIPART_FORM_DATA:
// Checks for new or modified string tuples
map = getTuples(lastRequestID, "String");
boolean stringComparison = areMapsIdentical(map, newState.getStringTuples());
states = getTuples(lastRequestID, "String");
boolean stringComparison = areListsEqual(states, newState.formStringTuples);
// Checks for new or modified file tuples
map = getTuples(lastRequestID, "File");
boolean fileComparison = areMapsIdentical(map, newState.getFileTuples());
states = getTuples(lastRequestID, "File");
boolean fileComparison = areListsEqual(states, newState.formFileTuples);
return stringComparison && fileComparison;
}
@ -318,19 +329,19 @@ public class HistoryManager {
return true;
}
private boolean areMapsIdentical(HashMap<String, String> firstMap, HashMap<String, String> secondMap) {
if (firstMap == null && secondMap == null)
private static boolean areListsEqual(ArrayList<FieldState> firstList, ArrayList<FieldState> secondList) {
if (firstList == null && secondList == null)
return true;
if ((firstMap == null && secondMap != null) ||
(firstMap != null && secondMap == null))
if ((firstList == null && secondList != null) ||
(firstList != null && secondList == null))
return false;
for (Entry entry : secondMap.entrySet()) {
if (!firstMap.containsKey(entry.getKey().toString()) ||
!firstMap.get(entry.getKey().toString()).equals(entry.getValue().toString()))
for (FieldState state : secondList) {
if (!firstList.contains(state))
return false;
}
return true;
}
@ -343,8 +354,8 @@ public class HistoryManager {
statement =
conn.prepareStatement(EverestUtilities.trimString(queries.get("saveRequest").toString()));
statement.setString(1, state.getHttpMethod());
statement.setString(2, String.valueOf(state.getTarget()));
statement.setString(1, state.httpMethod);
statement.setString(2, state.target);
statement.setString(3, LocalDate.now().toString());
statement.executeUpdate();
@ -357,41 +368,44 @@ public class HistoryManager {
if (RS.next())
requestID = RS.getInt("MaxID");
if (state.getHeaders().size() > 0) {
if (state.headers.size() > 0) {
// Saves request headers
statement = conn.prepareStatement(EverestUtilities.trimString(queries.get("saveHeader").toString()));
for (Entry entry : state.getHeaders().entrySet()) {
for (FieldState fieldState : state.headers) {
statement.setInt(1, requestID);
statement.setString(2, entry.getKey().toString());
statement.setString(3, entry.getValue().toString());
statement.setString(2, fieldState.key);
statement.setString(3, fieldState.value);
statement.setInt(4, fieldState.checked ? 1 : 0);
statement.executeUpdate();
}
}
if (state.getParams().size() > 0) {
if (state.params.size() > 0) {
// Saves request parameters
statement = conn.prepareStatement(EverestUtilities.trimString(queries.get("saveTuple").toString()));
for (Entry entry : state.getParams().entrySet()) {
for (FieldState fieldState : state.params) {
statement.setInt(1, requestID);
statement.setString(2, "Param");
statement.setString(3, entry.getKey().toString());
statement.setString(4, entry.getValue().toString());
statement.setString(3, fieldState.key);
statement.setString(4, fieldState.value);
statement.setInt(5, fieldState.checked ? 1 : 0);
statement.executeUpdate();
}
}
if (!(state.getHttpMethod().equals("GET") || state.getHttpMethod().equals("DELETE"))) {
// Maps the request to its ContentType for faster recovery
if (!(state.httpMethod.equals("GET") || state.httpMethod.equals("DELETE"))) {
// Maps the request to its ContentType for faster retrieval
statement = conn.prepareStatement(EverestUtilities.trimString(queries.get("saveRequestContentPair").toString()));
statement.setInt(1, requestID);
statement.setString(2, state.getContentType());
statement.setString(2, state.contentType);
statement.executeUpdate();
// Determines where to fetch the body from, based on the ContentType
switch (state.getContentType()) {
switch (state.contentType) {
case MediaType.TEXT_PLAIN:
case MediaType.APPLICATION_JSON:
case MediaType.APPLICATION_XML:
@ -400,45 +414,48 @@ public class HistoryManager {
// Saves the body in case of raw content, or the file location in case of binary
statement = conn.prepareStatement(EverestUtilities.trimString(queries.get("saveBody").toString()));
statement.setInt(1, requestID);
statement.setString(2, state.getBody());
statement.setString(2, state.rawBody);
statement.executeUpdate();
break;
case MediaType.APPLICATION_FORM_URLENCODED:
if (state.getStringTuples().size() > 0) {
for (Entry<String, String> entry : state.getStringTuples().entrySet()) {
if (state.urlStringTuples.size() > 0) {
for (FieldState fieldState : state.urlStringTuples) {
// Saves the string tuples
statement = conn.prepareStatement(EverestUtilities.trimString(queries.get("saveTuple").toString()));
statement.setInt(1, requestID);
statement.setString(2, "String");
statement.setString(3, entry.getKey());
statement.setString(4, entry.getValue());
statement.setString(3, fieldState.key);
statement.setString(4, fieldState.value);
statement.setInt(5, fieldState.checked ? 1 : 0);
statement.executeUpdate();
}
}
break;
case MediaType.MULTIPART_FORM_DATA:
if (state.getStringTuples().size() > 0) {
for (Entry<String, String> entry : state.getStringTuples().entrySet()) {
if (state.formStringTuples.size() > 0) {
for (FieldState fieldState : state.formStringTuples) {
// Saves the string tuples
statement = conn.prepareStatement(EverestUtilities.trimString(queries.get("saveTuple").toString()));
statement.setInt(1, requestID);
statement.setString(2, "String");
statement.setString(3, entry.getKey());
statement.setString(4, entry.getValue());
statement.setString(3, fieldState.key);
statement.setString(4, fieldState.value);
statement.setInt(5, fieldState.checked ? 1 : 0);
statement.executeUpdate();
}
}
if (state.getFileTuples().size() > 0) {
for (Entry<String, String> entry : state.getFileTuples().entrySet()) {
// Saves the file tuples
if (state.formFileTuples.size() > 0) {
for (FieldState fieldState : state.formFileTuples) {
// Saves the string tuples
statement = conn.prepareStatement(EverestUtilities.trimString(queries.get("saveTuple").toString()));
statement.setInt(1, requestID);
statement.setString(2, "File");
statement.setString(3, entry.getKey());
statement.setString(4, entry.getValue());
statement.setString(3, fieldState.key);
statement.setString(4, fieldState.value);
statement.setInt(5, fieldState.checked ? 1 : 0);
statement.executeUpdate();
}

View file

@ -1,62 +0,0 @@
/*
* Copyright 2018 Rohit Awate.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.rohitawate.everest.models;
import com.rohitawate.everest.models.requests.DataDispatchRequest;
import java.io.Serializable;
import java.util.HashMap;
/**
* Convenience class to abstract the state of the application.
*/
public class DashboardState extends DataDispatchRequest implements Serializable {
private HashMap<String, String> params;
private String httpMethod;
public DashboardState() {
}
/*
Special copy constructor to instantiate DashboardState from
BodyTabController's getBasicRequest()
*/
public DashboardState(DataDispatchRequest dataDispatchRequest) {
super();
this.setHttpMethod(dataDispatchRequest.getRequestType());
this.setBody(dataDispatchRequest.getBody());
this.setContentType(dataDispatchRequest.getContentType());
this.setStringTuples(dataDispatchRequest.getStringTuples());
this.setFileTuples(dataDispatchRequest.getFileTuples());
}
public void setParams(HashMap<String, String> params) {
this.params = params;
}
public HashMap<String, String> getParams() {
return params;
}
public void setHttpMethod(String httpMethod) {
this.httpMethod = httpMethod;
}
public String getHttpMethod() {
return httpMethod;
}
}

View file

@ -41,7 +41,8 @@ public class SettingsLoader implements Runnable {
try {
File settingsFile = new File("Everest/config/settings.json");
System.out.println("Settings file found. Loading settings... ");
if (settingsFile.exists())
System.out.println("Settings file found. Loading settings... ");
nodes = EverestUtilities.jsonMapper.readTree(settingsFile);

View file

@ -1,14 +1,14 @@
{
"createRequestsTable": "CREATE TABLE IF NOT EXISTS Requests(ID INTEGER PRIMARY KEY, Type TEXT NOT NULL, Target TEXT NOT NULL, Date TEXT NOT NULL)",
"createHeadersTable": "CREATE TABLE IF NOT EXISTS Headers(RequestID INTEGER, Key TEXT NOT NULL, Value TEXT NOT NULL, FOREIGN KEY(RequestID) REFERENCES Requests(ID))",
"createHeadersTable": "CREATE TABLE IF NOT EXISTS Headers(RequestID INTEGER, Key TEXT NOT NULL, Value TEXT NOT NULL, Checked INTEGER CHECK (Checked IN (0, 1)), FOREIGN KEY(RequestID) REFERENCES Requests(ID))",
"createRequestContentMapTable": "CREATE TABLE IF NOT EXISTS RequestContentMap(RequestID INTEGER, ContentType TEXT NOT NULL, FOREIGN KEY(RequestID) REFERENCES Requests(ID))",
"createBodiesTable": "CREATE TABLE IF NOT EXISTS Bodies(RequestID INTEGER, Body TEXT NOT NULL, FOREIGN KEY(RequestID) REFERENCES Requests(ID))",
"createTuplesTable": "CREATE TABLE IF NOT EXISTS Tuples(RequestID INTEGER, TupleType TEXT NOT NULL, Key TEXT NOT NULL, Value TEXT NOT NULL, FOREIGN KEY(RequestID) REFERENCES Requests(ID))",
"createTuplesTable": "CREATE TABLE IF NOT EXISTS Tuples(RequestID INTEGER, TupleType TEXT NOT NULL, Key TEXT NOT NULL, Value TEXT NOT NULL, Checked INTEGER CHECK (Checked IN (0, 1)), FOREIGN KEY(RequestID) REFERENCES Requests(ID))",
"saveRequest": "INSERT INTO Requests(Type, Target, Date) VALUES(?, ?, ?)",
"saveHeader": "INSERT INTO Headers(RequestID, Key, Value) VALUES(?, ?, ?)",
"saveHeader": "INSERT INTO Headers(RequestID, Key, Value, Checked) VALUES(?, ?, ?, ?)",
"saveRequestContentPair": "INSERT INTO RequestContentMap(RequestID, ContentType) VALUES(?, ?)",
"saveBody": "INSERT INTO Bodies(RequestID, Body) VALUES(?, ?)",
"saveTuple": "INSERT INTO Tuples(RequestID, TupleType, Key, Value) VALUES(?, ?, ?, ?)",
"saveTuple": "INSERT INTO Tuples(RequestID, TupleType, Key, Value, Checked) VALUES(?, ?, ?, ?, ?)",
"selectRecentRequests": "SELECT * FROM Requests WHERE Requests.Date > ?",
"selectRequestHeaders": "SELECT * FROM Headers WHERE RequestID == ?",
"selectRequestContentType": "SELECT ContentType FROM RequestContentMap WHERE RequestID == ?",