Merge branch 'core-optimization' into master

This commit is contained in:
Rohit Awate 2018-06-09 21:47:52 +05:30 committed by GitHub
commit 590554c6be
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 701 additions and 512 deletions

7
.gitignore vendored
View file

@ -4,9 +4,12 @@
classes/
src/main/java/META-INF/
dependency-reduced-pom.xml
Everest/
# Hides Eclipse Artifacts
.settings/
.classpath
.project
.project
/BugReporter/src/META-INF/
BugReporter/src/META-INF/
out/

10
.travis.yml Normal file
View file

@ -0,0 +1,10 @@
language: java
sudo: true
script: mvn clean package
deploy:
provider: releases
api_key:
secure: yep
file: target/Everest-Alpha-1.0.jar

View file

@ -14,8 +14,6 @@
* limitations under the License.
*/
package com.rohitawate.everest.util;
import java.io.*;
import java.nio.charset.Charset;
import java.time.LocalDate;
@ -28,44 +26,30 @@ public class BugReporter {
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
System.out.println("Everest Bug Reporting Service");
System.out.println();
System.out.println("Please describe the issue with as much detail and clarity as possible: ");
System.out.println("-----------------------------\n");
System.out.println("Please describe the issue with as much detail and clarity as possible (no newline): ");
String userMessage = scanner.nextLine();
StringBuilder builder = new StringBuilder();
builder.append("\nThank you for your input! The issue was recorded.\n\n");
builder.append("With your permission, this service can collect some anonymous, non-personal information about your system.\n");
builder.append("This information will help us to better reproduce the issue and fix it quickly.\n");
builder.append("This includes:\n");
builder.append(" - Operating system details.\n");
builder.append(" - Details about your Java Runtime Environment.\n\n");
builder.append("Allow? (Y/N)\n>> ");
System.out.print(builder.toString());
String allowSystemData = scanner.nextLine();
allowSystemData = allowSystemData.toLowerCase();
StringBuilder report = new StringBuilder();
report.append("Log date: ");
report.append(LocalDateTime.now());
report.append("\n\n");
if (allowSystemData.equals("y") || allowSystemData.equals("yes")) {
report.append(generateSystemDetails());
System.out.println("\nThat's great! We will include your system details in with the bug report.");
} else {
System.out.println("\nAlrighty! We will only include Everest's log files in the report.");
}
scanner.close();
report.append("User Message:\n");
report.append(userMessage);
generateReport(report.toString());
generateReportFile(generateReport(userMessage));
generateZipFile();
System.out.println("\nYour issue was successfully reported and will be fixed soon.");
System.out.println("\nYour report was submitted successfully reported and will be evaluated soon.");
System.out.println("Thank you! :)");
}
private static String generateSystemDetails() {
private static String generateReport(String userMessage) {
StringBuilder report = new StringBuilder();
report.append("Report date: ");
report.append(LocalDateTime.now());
report.append("\n\n");
report.append(getSystemDetails());
report.append("User Message:\n");
report.append(userMessage);
return report.toString();
}
private static String getSystemDetails() {
StringBuilder builder = new StringBuilder();
String OS = System.getProperty("os.name");
if (OS.equals("Linux")) {
@ -77,19 +61,18 @@ public class BugReporter {
builder.append(System.getProperty("os.arch"));
builder.append(" ");
builder.append(System.getProperty("os.version"));
builder.append("\n");
builder.append("Java VM: ");
builder.append("\nJava VM: ");
builder.append(System.getProperty("java.vm.name"));
builder.append(" ");
builder.append("\nVM Version: ");
builder.append(System.getProperty("java.version"));
builder.append("\nJava VM Vendor: ");
builder.append("\nVM Vendor: ");
builder.append(System.getProperty("java.vendor"));
builder.append("\n\n");
return builder.toString();
}
private static void generateReport(String reportContents) {
private static void generateReportFile(String reportContents) {
String reportFileName = "Report - " + LocalDate.now() + ".txt";
try {
BufferedWriter writer = new BufferedWriter(new FileWriter("logs/" + reportFileName));
@ -104,7 +87,7 @@ public class BugReporter {
try {
Scanner scanner;
FileInputStream fileInputStream;
ZipOutputStream zipStream = new ZipOutputStream(new FileOutputStream("Logs.zip"), Charset.forName("UTF-8"));
ZipOutputStream zipStream = new ZipOutputStream(new FileOutputStream("BugReport-" + LocalDate.now() + ".zip"), Charset.forName("UTF-8"));
File sourceDir = new File("logs/");
String[] logFiles = sourceDir.list();
@ -132,7 +115,7 @@ public class BugReporter {
}
private static String getLinuxDetails() {
String line = "";
String line;
try {
File etcDir = new File("/etc/");

View file

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: com.jfoenix:jfoenix:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.glassfish.jersey.core:jersey-client:2.26" level="project" />
<orderEntry type="library" name="Maven: org.glassfish.jersey.core:jersey-common:2.26" level="project" />
<orderEntry type="library" name="Maven: javax.annotation:javax.annotation-api:1.2" level="project" />
<orderEntry type="library" name="Maven: org.glassfish.hk2:osgi-resource-locator:1.0.1" level="project" />
<orderEntry type="library" name="Maven: org.glassfish.hk2.external:javax.inject:2.5.0-b42" level="project" />
<orderEntry type="library" name="Maven: javax.ws.rs:javax.ws.rs-api:2.1" level="project" />
<orderEntry type="library" name="Maven: org.glassfish.jersey.media:jersey-media-multipart:2.26" level="project" />
<orderEntry type="library" name="Maven: org.jvnet.mimepull:mimepull:1.9.6" level="project" />
<orderEntry type="library" name="Maven: org.glassfish.jersey.inject:jersey-hk2:2.26" level="project" />
<orderEntry type="library" name="Maven: org.glassfish.hk2:hk2-locator:2.5.0-b42" level="project" />
<orderEntry type="library" name="Maven: org.glassfish.hk2.external:aopalliance-repackaged:2.5.0-b42" level="project" />
<orderEntry type="library" name="Maven: org.glassfish.hk2:hk2-api:2.5.0-b42" level="project" />
<orderEntry type="library" name="Maven: javax.inject:javax.inject:1" level="project" />
<orderEntry type="library" name="Maven: org.glassfish.hk2:hk2-utils:2.5.0-b42" level="project" />
<orderEntry type="library" name="Maven: org.javassist:javassist:3.22.0-CR2" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.9.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.9.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.9.0" level="project" />
<orderEntry type="library" name="Maven: org.xerial:sqlite-jdbc:3.21.0.1" level="project" />
<orderEntry type="library" name="Maven: com.google.guava:guava:24.1-jre" level="project" />
<orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:1.3.9" level="project" />
<orderEntry type="library" name="Maven: org.checkerframework:checker-compat-qual:2.0.0" level="project" />
<orderEntry type="library" name="Maven: com.google.errorprone:error_prone_annotations:2.1.3" level="project" />
<orderEntry type="library" name="Maven: com.google.j2objc:j2objc-annotations:1.1" level="project" />
<orderEntry type="library" name="Maven: org.codehaus.mojo:animal-sniffer-annotations:1.14" level="project" />
</component>
</module>

View file

@ -45,7 +45,7 @@
<!-- add Main-Class to manifest file -->
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.rohitawate.everest.main.Main</mainClass>
<mainClass>com.rohitawate.everest.Main</mainClass>
</transformer>
</transformers>
</configuration>

View file

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.rohitawate.everest.main;
package com.rohitawate.everest;
import com.rohitawate.everest.util.EverestUtilities;
import com.rohitawate.everest.util.Services;
@ -21,9 +21,11 @@ import com.rohitawate.everest.util.settings.SettingsLoader;
import com.rohitawate.everest.util.themes.ThemeManager;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Rectangle2D;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Screen;
import javafx.stage.Stage;
public class Main extends Application {
@ -41,6 +43,10 @@ public class Main extends Application {
Stage dashboardStage = new Stage();
ThemeManager.setTheme(homeWindow);
Rectangle2D screenBounds = Screen.getPrimary().getBounds();
dashboardStage.setWidth(screenBounds.getWidth() * 0.83);
dashboardStage.setHeight(screenBounds.getHeight() * 0.74);
dashboardStage.getIcons().add(new Image(getClass().getResource("/assets/Logo.png").toExternalForm()));
dashboardStage.setScene(new Scene(homeWindow));
dashboardStage.setTitle("Everest");

View file

@ -44,16 +44,16 @@ public class BodyTabController implements Initializable {
@FXML
private TabPane bodyTabPane;
@FXML
private ComboBox<String> rawInputTypeBox;
ComboBox<String> rawInputTypeBox;
@FXML
private TextArea rawInputArea;
TextArea rawInputArea;
@FXML
private Tab rawTab, binaryTab, formTab, urlTab;
Tab rawTab, binaryTab, formTab, urlTab;
@FXML
private TextField filePathField;
TextField filePathField;
private FormDataTabController formDataTabController;
private URLTabController urlTabController;
FormDataTabController formDataTabController;
URLTabController urlTabController;
@Override
public void initialize(URL location, ResourceBundle resources) {
@ -135,24 +135,16 @@ public class BodyTabController implements Initializable {
try {
switch (dashboardState.getContentType()) {
case MediaType.TEXT_PLAIN:
rawInputArea.setText(dashboardState.getBody());
rawInputTypeBox.getSelectionModel().select("PLAIN TEXT");
bodyTabPane.getSelectionModel().select(rawTab);
setRawTab(dashboardState, "PLAIN TEXT");
break;
case MediaType.APPLICATION_JSON:
rawInputArea.setText(dashboardState.getBody());
rawInputTypeBox.getSelectionModel().select("JSON");
bodyTabPane.getSelectionModel().select(rawTab);
setRawTab(dashboardState, "JSON");
break;
case MediaType.APPLICATION_XML:
rawInputArea.setText(dashboardState.getBody());
rawInputTypeBox.getSelectionModel().select("XML");
bodyTabPane.getSelectionModel().select(rawTab);
setRawTab(dashboardState, "XML");
break;
case MediaType.TEXT_HTML:
rawInputArea.setText(dashboardState.getBody());
rawInputTypeBox.getSelectionModel().select("HTML");
bodyTabPane.getSelectionModel().select(rawTab);
setRawTab(dashboardState, "HTML");
break;
case MediaType.MULTIPART_FORM_DATA:
// For file tuples
@ -178,4 +170,10 @@ public class BodyTabController implements Initializable {
Services.loggingService.logInfo("Dashboard loaded with blank request body.", LocalDateTime.now());
}
}
private void setRawTab(DashboardState dashboardState, String contentType) {
rawInputArea.setText(dashboardState.getBody());
rawInputTypeBox.getSelectionModel().select(contentType);
bodyTabPane.getSelectionModel().select(rawTab);
}
}

View file

@ -17,6 +17,7 @@ package com.rohitawate.everest.controllers;
import com.fasterxml.jackson.databind.JsonNode;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXProgressBar;
import com.jfoenix.controls.JFXSnackbar;
import com.rohitawate.everest.exceptions.RedirectException;
import com.rohitawate.everest.exceptions.UnreliableResponseException;
@ -25,9 +26,7 @@ import com.rohitawate.everest.models.requests.DELETERequest;
import com.rohitawate.everest.models.requests.DataDispatchRequest;
import com.rohitawate.everest.models.requests.GETRequest;
import com.rohitawate.everest.models.responses.EverestResponse;
import com.rohitawate.everest.requestmanager.DELETERequestManager;
import com.rohitawate.everest.requestmanager.DataDispatchRequestManager;
import com.rohitawate.everest.requestmanager.GETRequestManager;
import com.rohitawate.everest.requestmanager.RequestManager;
import com.rohitawate.everest.util.EverestUtilities;
import com.rohitawate.everest.util.Services;
@ -40,7 +39,6 @@ import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.CacheHint;
import javafx.scene.Parent;
import javafx.scene.control.*;
import javafx.scene.input.KeyCode;
@ -49,14 +47,18 @@ import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javax.ws.rs.ProcessingException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.*;
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 {
@FXML
@ -75,15 +77,15 @@ public class DashboardController implements Initializable {
private Label statusCode, statusCodeDescription, responseTime,
responseSize, errorTitle, errorDetails, responseType;
@FXML
private JFXButton sendButton, cancelButton;
private JFXButton cancelButton, copyBodyButton;
@FXML
TabPane requestOptionsTab;
@FXML
Tab paramsTab, authTab, headersTab, bodyTab;
@FXML
private Tab visualizerTab;
private Tab visualizerTab, responseHeadersTab;
@FXML
private ScrollPane visualizer;
private JFXProgressBar progressBar;
private JFXSnackbar snackbar;
private final String[] httpMethods = {"GET", "POST", "PUT", "DELETE", "PATCH"};
@ -93,7 +95,13 @@ public class DashboardController implements Initializable {
private HeaderTabController headerTabController;
private BodyTabController bodyTabController;
private IntegerProperty paramsCountProperty;
private Accordion accordion;
private Visualizer visualizer;
private ResponseHeadersViewer responseHeadersViewer;
private GETRequest getRequest;
private DataDispatchRequest dataRequest;
private DELETERequest deleteRequest;
private HashMap<String, String> params;
@Override
public void initialize(URL url, ResourceBundle rb) {
@ -143,14 +151,30 @@ public class DashboardController implements Initializable {
}
});
copyBodyButton.setOnAction(e -> {
responseArea.selectAll();
responseArea.copy();
responseArea.deselect();
snackbar.show("Response body copied to clipboard.", 5000);
});
errorTitle.setText("Oops... That's embarrassing!");
errorDetails.setText("Something went wrong. Try to make another request.\nRestart Everest if that doesn't work.");
setupVisualizer();
visualizer = new Visualizer();
visualizerTab.setContent(visualizer);
responseHeadersViewer = new ResponseHeadersViewer();
responseHeadersTab.setContent(responseHeadersViewer);
}
@FXML
void sendRequest() {
if (requestManager != null && requestManager.isRunning()) {
snackbar.show("Please wait while the current request is processed.", 5000);
return;
}
promptLayer.setVisible(false);
if (responseBox.getChildren().size() == 2) {
responseBox.getChildren().remove(0);
@ -159,6 +183,14 @@ public class DashboardController implements Initializable {
try {
String address = addressField.getText();
// Prepends "https://" to the address if not already done.
if (!(address.startsWith("https://") || address.startsWith("http://"))) {
address = "https://" + address;
addressField.setText(address);
responseArea.requestFocus();
}
if (address.equals("")) {
promptLayer.setVisible(true);
snackbar.show("Please enter an address.", 3000);
@ -166,62 +198,78 @@ public class DashboardController implements Initializable {
}
switch (httpMethodBox.getValue()) {
case "GET":
GETRequest getRequest = new GETRequest(addressField.getText());
getRequest.setHeaders(headerTabController.getHeaders());
if (getRequest == null)
getRequest = new GETRequest();
/*
Creates a new instance if its the first request of that session or
the HTTP method type was changed. Also checks if a request is already being processed.
*/
if (requestManager == null || requestManager.getClass() != GETRequestManager.class)
requestManager = new GETRequestManager(getRequest);
else if (requestManager.isRunning()) {
snackbar.show("Please wait while the current request is processed.", 3000);
return;
} else {
requestManager.setRequest(getRequest);
}
getRequest.setTarget(address);
getRequest.setHeaders(headerTabController.getSelectedHeaders());
requestManager = Services.pool.get();
requestManager.setRequest(getRequest);
cancelButton.setOnAction(e -> requestManager.cancel());
configureRequestManager();
requestManager.start();
break;
// DataDispatchRequestManager will generate appropriate request based on the type.
case "POST":
case "PUT":
case "PATCH":
DataDispatchRequest dataDispatchRequest =
bodyTabController.getBasicRequest(httpMethodBox.getValue());
dataDispatchRequest.setTarget(addressField.getText());
dataDispatchRequest.setHeaders(headerTabController.getHeaders());
if (dataRequest == null)
dataRequest = new DataDispatchRequest();
if (requestManager == null || requestManager.getClass() != DataDispatchRequestManager.class)
requestManager = new DataDispatchRequestManager(dataDispatchRequest);
else if (requestManager.isRunning()) {
snackbar.show("Please wait while the current request is processed.", 3000);
return;
} else {
requestManager.setRequest(dataDispatchRequest);
dataRequest.setRequestType(httpMethodBox.getValue());
dataRequest.setTarget(address);
dataRequest.setHeaders(headerTabController.getSelectedHeaders());
if (bodyTabController.rawTab.isSelected()) {
String contentType;
switch (bodyTabController.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;
}
dataRequest.setContentType(contentType);
dataRequest.setBody(bodyTabController.rawInputArea.getText());
} else if (bodyTabController.formTab.isSelected()) {
dataRequest.setStringTuples(bodyTabController.formDataTabController.getStringTuples());
dataRequest.setFileTuples(bodyTabController.formDataTabController.getFileTuples());
dataRequest.setContentType(MediaType.MULTIPART_FORM_DATA);
} else if (bodyTabController.binaryTab.isSelected()) {
dataRequest.setBody(bodyTabController.filePathField.getText());
dataRequest.setContentType(MediaType.APPLICATION_OCTET_STREAM);
} else if (bodyTabController.urlTab.isSelected()) {
dataRequest.setStringTuples(bodyTabController.urlTabController.getStringTuples());
dataRequest.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
}
requestManager = Services.pool.data();
requestManager.setRequest(dataRequest);
cancelButton.setOnAction(e -> requestManager.cancel());
configureRequestManager();
requestManager.start();
break;
case "DELETE":
DELETERequest deleteRequest = new DELETERequest(addressField.getText());
deleteRequest.setHeaders(headerTabController.getHeaders());
if (deleteRequest == null)
deleteRequest = new DELETERequest();
if (requestManager == null || requestManager.getClass() != DELETERequestManager.class)
requestManager = new DELETERequestManager(deleteRequest);
else if (requestManager.isRunning()) {
snackbar.show("Please wait while the current request is processed.", 3000);
return;
} else {
requestManager.setRequest(deleteRequest);
}
deleteRequest.setTarget(address);
deleteRequest.setHeaders(headerTabController.getSelectedHeaders());
requestManager = Services.pool.delete();
requestManager.setRequest(deleteRequest);
cancelButton.setOnAction(e -> requestManager.cancel());
configureRequestManager();
requestManager.start();
@ -242,6 +290,7 @@ public class DashboardController implements Initializable {
}
private void configureRequestManager() {
progressBar.progressProperty().bind(requestManager.progressProperty());
requestManager.setOnRunning(e -> whileRunning());
requestManager.setOnSucceeded(e -> onSucceeded());
requestManager.setOnCancelled(e -> onCancelled());
@ -293,7 +342,7 @@ public class DashboardController implements Initializable {
}
private void onSucceeded() {
updateDashboard(requestManager.getValue());
displayResponse(requestManager.getValue());
errorLayer.setVisible(false);
loadingLayer.setVisible(false);
requestManager.reset();
@ -305,13 +354,14 @@ public class DashboardController implements Initializable {
loadingLayer.setVisible(true);
}
private void updateDashboard(EverestResponse response) {
private void displayResponse(EverestResponse response) {
prettifyResponseBody(response);
responseBox.getChildren().add(0, responseDetails);
statusCode.setText(Integer.toString(response.getStatusCode()));
statusCodeDescription.setText(Response.Status.fromStatusCode(response.getStatusCode()).getReasonPhrase());
responseTime.setText(Long.toString(response.getTime()) + " ms");
responseSize.setText(Integer.toString(response.getSize()) + " B");
responseHeadersViewer.populate(response);
}
private void prettifyResponseBody(EverestResponse response) {
@ -324,20 +374,20 @@ public class DashboardController implements Initializable {
String responseBody = response.getBody();
visualizerTab.setDisable(true);
visualizer.clear();
try {
if (type != null) {
// Selects only the part preceding the ';', skipping the character encoding
type = type.split(";")[0];
visualizerTab.setDisable(true);
switch (type.toLowerCase()) {
case "application/json":
responseType.setText("JSON");
JsonNode node = EverestUtilities.mapper.readTree(responseBody);
responseArea.setText(EverestUtilities.mapper.writeValueAsString(node));
accordion.getPanes().clear();
visualizerTab.setDisable(false);
populateVisualizer(accordion, "root", node);
visualizer.populate(node);
break;
case "application/xml":
responseType.setText("XML");
@ -364,84 +414,6 @@ public class DashboardController implements Initializable {
}
}
private void setupVisualizer() {
accordion = new Accordion();
accordion.setCache(true);
accordion.setCacheHint(CacheHint.SPEED);
visualizer.setContent(accordion);
}
private void populateVisualizer(Accordion rootAccordion, String rootName, JsonNode root) {
JsonNode currentNode;
VBox container = new VBox();
container.setStyle("-fx-padding: 3px 30px");
Label valueLabel;
TitledPane pane = new TitledPane(rootName, container);
Tooltip valueTooltip;
if (root.isArray()) {
Iterator<JsonNode> iterator = root.elements();
while (iterator.hasNext()) {
currentNode = iterator.next();
if (currentNode.isValueNode()) {
valueLabel = new Label(currentNode.toString());
valueLabel.getStyleClass().add("visualizerValueLabel");
valueLabel.setWrapText(true);
valueTooltip = new Tooltip(currentNode.toString());
valueLabel.setTooltip(valueTooltip);
container.getChildren().add(valueLabel);
} else if (currentNode.isObject()) {
Accordion arrayAccordion = new Accordion();
container.getChildren().add(arrayAccordion);
populateVisualizer(arrayAccordion, "", currentNode);
}
}
rootAccordion.getPanes().add(pane);
} else {
Iterator<Entry<String, JsonNode>> iterator = root.fields();
Entry<String, JsonNode> currentEntry;
HBox valueContainer;
Label keyLabel;
Tooltip keyTooltip;
while (iterator.hasNext()) {
currentEntry = iterator.next();
currentNode = currentEntry.getValue();
if (currentNode.isValueNode()) {
keyLabel = new Label(currentEntry.getKey() + ": ");
keyLabel.setStyle("-fx-font-weight: bold");
keyLabel.getStyleClass().add("visualizerKeyLabel");
keyTooltip = new Tooltip(currentEntry.getKey());
keyLabel.setTooltip(keyTooltip);
valueLabel = new Label(currentNode.toString());
valueLabel.getStyleClass().add("visualizerValueLabel");
valueLabel.setWrapText(true);
valueTooltip = new Tooltip(currentNode.toString());
valueLabel.setTooltip(valueTooltip);
valueContainer = new HBox(keyLabel, valueLabel);
container.getChildren().add(valueContainer);
} else if (currentNode.isArray() || currentNode.isObject()) {
Accordion arrayAccordion = new Accordion();
container.getChildren().add(arrayAccordion);
populateVisualizer(arrayAccordion, currentEntry.getKey(), currentNode);
}
}
rootAccordion.getPanes().add(pane);
}
if (!rootName.equals("root")) {
pane.getStyleClass().add("nonRootTitledPane"); // Special CSS class to set padding for non-root panes only
} else {
rootAccordion.setExpandedPane(pane);
}
}
private void applyDashboardSettings() {
String responseAreaCSS = "-fx-font-family: " + Settings.responseAreaFont + ";" +
"-fx-font-size: " + Settings.responseAreaFontSize;
@ -472,8 +444,10 @@ public class DashboardController implements Initializable {
}
private HashMap<String, String> getParams() {
HashMap<String, String> params = new HashMap<>();
if (params == null)
params = new HashMap<>();
params.clear();
for (StringKeyValueFieldController controller : paramsControllers)
if (controller.isChecked())
params.put(controller.getHeader().getKey(), controller.getHeader().getValue());
@ -542,7 +516,7 @@ public class DashboardController implements Initializable {
case "PUT":
case "PATCH":
dashboardState = new DashboardState(bodyTabController.getBasicRequest(httpMethodBox.getValue()));
dashboardState.setHeaders(headerTabController.getHeaders());
dashboardState.setHeaders(headerTabController.getSelectedHeaders());
break;
default:
// For GET, DELETE requests
@ -555,7 +529,7 @@ public class DashboardController implements Initializable {
Services.loggingService.logInfo("Dashboard state was saved with an invalid URL.", LocalDateTime.now());
}
dashboardState.setHttpMethod(httpMethodBox.getValue());
dashboardState.setHeaders(headerTabController.getHeaders());
dashboardState.setHeaders(headerTabController.getSelectedHeaders());
dashboardState.setParams(getParams());
return dashboardState;

View file

@ -44,6 +44,9 @@ public class FormDataTabController implements Initializable {
private List<FileKeyValueFieldController> fileControllers;
private IntegerProperty fileControllersCount, stringControllersCount;
private HashMap<String, String> stringMap;
private HashMap<String, String> fileMap;
@Override
public void initialize(URL location, ResourceBundle resources) {
stringControllers = new ArrayList<>();
@ -56,24 +59,22 @@ public class FormDataTabController implements Initializable {
addStringField();
}
private void addFileField() {
addFileField("", "", null);
}
@FXML
private void addFileField(ActionEvent event) {
addFileField("", "", event);
}
private void addFileField() {
addFileField("", "", null);
}
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.
*/
//Re-uses previous field if it is empty else loads a new one.
if (fileControllers.size() > 0 && event == null) {
FileKeyValueFieldController previousController = fileControllers.get(fileControllers.size() - 1);
@ -106,15 +107,15 @@ public class FormDataTabController implements Initializable {
}
}
private void addStringField() {
addStringField("", "", null);
}
@FXML
private void addStringField(ActionEvent event) {
addStringField("", "", event);
}
private void addStringField() {
addStringField("", "", null);
}
public void addStringField(String key, String value) {
addStringField(key, value, null);
}
@ -156,20 +157,26 @@ public class FormDataTabController implements Initializable {
}
public HashMap<String, String> getStringTuples() {
HashMap<String, String> tuples = new HashMap<>();
if (stringMap == null)
stringMap = new HashMap<>();
stringMap.clear();
for (StringKeyValueFieldController controller : stringControllers) {
if (controller.isChecked())
tuples.put(controller.getHeader().getKey(), controller.getHeader().getValue());
stringMap.put(controller.getHeader().getKey(), controller.getHeader().getValue());
}
return tuples;
return stringMap;
}
public HashMap<String, String> getFileTuples() {
HashMap<String, String> tuples = new HashMap<>();
if (fileMap == null)
fileMap = new HashMap<>();
fileMap.clear();
for (FileKeyValueFieldController controller : fileControllers) {
if (controller.isChecked())
tuples.put(controller.getHeader().getKey(), controller.getHeader().getValue());
fileMap.put(controller.getHeader().getKey(), controller.getHeader().getValue());
}
return tuples;
return fileMap;
}
}

View file

@ -43,6 +43,8 @@ public class HeaderTabController implements Initializable {
private List<StringKeyValueFieldController> controllers;
private IntegerProperty controllersCount;
private HashMap<String, String> headers;
@Override
public void initialize(URL location, ResourceBundle resources) {
controllers = new ArrayList<>();
@ -100,9 +102,14 @@ public class HeaderTabController implements Initializable {
}
}
/**
* Returns a map of the selected headers.
*/
public HashMap<String, String> getSelectedHeaders() {
if (headers == null)
headers = new HashMap<>();
public HashMap<String, String> getHeaders() {
HashMap<String, String> headers = new HashMap<>();
headers.clear();
for (StringKeyValueFieldController controller : controllers) {
if (controller.isChecked())
headers.put(controller.getHeader().getKey(), controller.getHeader().getValue());

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;
import com.rohitawate.everest.models.responses.EverestResponse;
import javafx.geometry.Insets;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
class ResponseHeadersViewer extends ScrollPane {
private VBox container;
ResponseHeadersViewer() {
this.container = new VBox();
container.setPadding(new Insets(10, 20, 10, 20));
this.setContent(container);
this.setFitToHeight(true);
this.setFitToWidth(true);
}
void populate(EverestResponse response) {
container.getChildren().clear();
response.getHeaders().forEach((key, value) -> {
Label keyLabel = new Label(key + ": ");
keyLabel.getStyleClass().addAll("visualizerKeyLabel", "visualizerLabel");
Label valueLabel = new Label(value.get(0));
valueLabel.getStyleClass().addAll("visualizerValueLabel", "visualizerLabel");
container.getChildren().add(new HBox(keyLabel, valueLabel));
});
}
}

View file

@ -42,6 +42,7 @@ public class URLTabController implements Initializable {
private List<StringKeyValueFieldController> controllers;
private IntegerProperty controllersCount;
private HashMap<String, String> tuples;
@Override
public void initialize(URL location, ResourceBundle resources) {
@ -101,11 +102,14 @@ public class URLTabController implements Initializable {
}
public HashMap<String, String> getStringTuples() {
HashMap<String, String> headers = new HashMap<>();
if (tuples == null)
tuples = new HashMap<>();
tuples.clear();
for (StringKeyValueFieldController controller : controllers) {
if (controller.isChecked())
headers.put(controller.getHeader().getKey(), controller.getHeader().getValue());
tuples.put(controller.getHeader().getKey(), controller.getHeader().getValue());
}
return headers;
return tuples;
}
}

View file

@ -0,0 +1,119 @@
/*
* 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;
import com.fasterxml.jackson.databind.JsonNode;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
class Visualizer extends ScrollPane {
private TreeView<HBox> visualizer;
Visualizer() {
this.visualizer = new TreeView<>();
this.visualizer.setShowRoot(false);
this.setContent(this.visualizer);
this.setFitToHeight(true);
this.setFitToWidth(true);
}
void populate(JsonNode node) {
this.populate(new TreeItem<>(), "root", node);
}
private void populate(TreeItem<HBox> rootItem, String rootName, JsonNode root) {
if (rootName.equals("root")) {
this.visualizer.setRoot(rootItem);
}
Label rootLabel = new Label(rootName);
rootLabel.getStyleClass().addAll("visualizerRootLabel", "visualizerLabel");
rootItem.setValue(new HBox(rootLabel));
JsonNode currentNode;
Label valueLabel;
HBox valueContainer;
List<TreeItem<HBox>> items = new LinkedList<>();
Tooltip valueTooltip;
if (root.isArray()) {
Iterator<JsonNode> iterator = root.elements();
int i = 0;
while (iterator.hasNext()) {
currentNode = iterator.next();
if (currentNode.isValueNode()) {
valueLabel = new Label(i++ + ": " + currentNode.toString());
valueLabel.getStyleClass().addAll("visualizerValueLabel", "visualizerLabel");
valueLabel.setWrapText(true);
valueTooltip = new Tooltip(currentNode.toString());
valueLabel.setTooltip(valueTooltip);
valueContainer = new HBox(valueLabel);
items.add(new TreeItem<>(valueContainer));
} else if (currentNode.isObject()) {
TreeItem<HBox> newRoot = new TreeItem<>();
items.add(newRoot);
populate(newRoot, i++ + ": [Anonymous Object]", currentNode);
}
}
} else {
Iterator<Map.Entry<String, JsonNode>> iterator = root.fields();
Map.Entry<String, JsonNode> currentEntry;
Label keyLabel;
Tooltip keyTooltip;
while (iterator.hasNext()) {
currentEntry = iterator.next();
currentNode = currentEntry.getValue();
if (currentNode.isValueNode()) {
keyLabel = new Label(currentEntry.getKey() + ": ");
keyLabel.getStyleClass().addAll("visualizerKeyLabel", "visualizerLabel");
keyTooltip = new Tooltip(currentEntry.getKey());
keyLabel.setTooltip(keyTooltip);
valueLabel = new Label(currentNode.toString());
valueLabel.getStyleClass().addAll("visualizerValueLabel", "visualizerLabel");
valueLabel.setWrapText(true);
valueTooltip = new Tooltip(currentNode.toString());
valueLabel.setTooltip(valueTooltip);
valueContainer = new HBox(keyLabel, valueLabel);
items.add(new TreeItem<>(valueContainer));
} else if (currentNode.isArray() || currentNode.isObject()) {
TreeItem<HBox> newRoot = new TreeItem<>();
items.add(newRoot);
populate(newRoot, currentEntry.getKey(), currentNode);
}
}
}
rootItem.getChildren().addAll(items);
}
public void clear() {
this.visualizer.setRoot(null);
}
}

View file

@ -71,4 +71,8 @@ public class DataDispatchRequest extends EverestRequest implements Serializable
public String getRequestType() {
return requestType;
}
public void setRequestType(String requestType) {
this.requestType = requestType;
}
}

View file

@ -17,6 +17,7 @@
package com.rohitawate.everest.models.responses;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
public class EverestResponse {
private String body;
@ -24,6 +25,7 @@ public class EverestResponse {
private long time;
private int size;
private MediaType mediaType;
private MultivaluedMap<String, String> headers;
public String getBody() {
return body;
@ -64,4 +66,12 @@ public class EverestResponse {
public void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}
public MultivaluedMap<String, String> getHeaders() {
return headers;
}
public void setHeaders(MultivaluedMap<String, String> headers) {
this.headers = headers;
}
}

View file

@ -16,7 +16,6 @@
package com.rohitawate.everest.requestmanager;
import com.rohitawate.everest.models.requests.EverestRequest;
import com.rohitawate.everest.models.responses.EverestResponse;
import javafx.concurrent.Task;
@ -25,8 +24,8 @@ import javax.ws.rs.core.Response;
public class DELETERequestManager extends RequestManager {
public DELETERequestManager(EverestRequest request) {
super(request);
DELETERequestManager() {
}
@Override
@ -36,9 +35,9 @@ public class DELETERequestManager extends RequestManager {
protected EverestResponse call() throws Exception {
Invocation invocation = requestBuilder.buildDelete();
long initialTime = System.currentTimeMillis();
initialTime = System.currentTimeMillis();
Response serverResponse = invocation.invoke();
response.setTime(initialTime, System.currentTimeMillis());
finalTime = System.currentTimeMillis();
processServerResponse(serverResponse);

View file

@ -17,7 +17,6 @@
package com.rohitawate.everest.requestmanager;
import com.rohitawate.everest.models.requests.DataDispatchRequest;
import com.rohitawate.everest.models.requests.EverestRequest;
import com.rohitawate.everest.models.responses.EverestResponse;
import javafx.concurrent.Task;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
@ -42,8 +41,8 @@ public class DataDispatchRequestManager extends RequestManager {
private DataDispatchRequest dataDispatchRequest;
private String requestType;
public DataDispatchRequestManager(EverestRequest request) {
super(request);
DataDispatchRequestManager() {
}
@Override
@ -55,9 +54,9 @@ public class DataDispatchRequestManager extends RequestManager {
requestType = dataDispatchRequest.getRequestType();
Invocation invocation = appendBody();
long initialTime = System.currentTimeMillis();
initialTime = System.currentTimeMillis();
Response serverResponse = invocation.invoke();
response.setTime(initialTime, System.currentTimeMillis());
finalTime = System.currentTimeMillis();
processServerResponse(serverResponse);
@ -73,6 +72,11 @@ public class DataDispatchRequestManager extends RequestManager {
* @return invocation object
*/
private Invocation appendBody() throws Exception {
/*
Checks if a custom mime-type is mentioned in the headers.
If present, it will override the logical Content-Type.
*/
String overriddenContentType = request.getHeaders().get("Content-Type");
Invocation invocation = null;
Map.Entry<String, String> mapEntry;
@ -80,6 +84,7 @@ public class DataDispatchRequestManager extends RequestManager {
case MediaType.MULTIPART_FORM_DATA:
FormDataMultiPart formData = new FormDataMultiPart();
// Adding the string tuples to the request
HashMap<String, String> pairs = dataDispatchRequest.getStringTuples();
for (Map.Entry entry : pairs.entrySet()) {
mapEntry = (Map.Entry) entry;
@ -89,8 +94,10 @@ public class DataDispatchRequestManager extends RequestManager {
String filePath;
File file;
boolean fileException = false;
StringBuilder fileExceptionMessage = new StringBuilder();
String fileExceptionMessage = null;
pairs = dataDispatchRequest.getFileTuples();
// Adding the file tuples to the request
for (Map.Entry entry : pairs.entrySet()) {
mapEntry = (Map.Entry) entry;
filePath = mapEntry.getValue();
@ -101,14 +108,13 @@ public class DataDispatchRequestManager extends RequestManager {
file, MediaType.APPLICATION_OCTET_STREAM_TYPE));
else {
fileException = true;
fileExceptionMessage.append(" - ");
fileExceptionMessage.append(filePath);
fileExceptionMessage.append("\n");
// For pretty-printing FileNotFoundException to the UI
fileExceptionMessage = " - " + filePath + "\n";
}
}
if (fileException) {
throw new FileNotFoundException(fileExceptionMessage.toString());
throw new FileNotFoundException(fileExceptionMessage);
}
formData.setMediaType(MediaType.MULTIPART_FORM_DATA_TYPE);
@ -119,6 +125,8 @@ public class DataDispatchRequestManager extends RequestManager {
invocation = requestBuilder.buildPut(Entity.entity(formData, MediaType.MULTIPART_FORM_DATA_TYPE));
break;
case MediaType.APPLICATION_OCTET_STREAM:
if (overriddenContentType == null)
overriddenContentType = MediaType.APPLICATION_OCTET_STREAM;
filePath = dataDispatchRequest.getBody();
File check = new File(filePath);
@ -130,11 +138,14 @@ public class DataDispatchRequestManager extends RequestManager {
FileInputStream stream = new FileInputStream(filePath);
if (requestType.equals("POST"))
invocation = requestBuilder.buildPost(Entity.entity(stream, MediaType.APPLICATION_OCTET_STREAM_TYPE));
invocation = requestBuilder.buildPost(Entity.entity(stream, overriddenContentType));
else
invocation = requestBuilder.buildPut(Entity.entity(stream, MediaType.APPLICATION_OCTET_STREAM_TYPE));
invocation = requestBuilder.buildPut(Entity.entity(stream, overriddenContentType));
break;
case MediaType.APPLICATION_FORM_URLENCODED:
if (overriddenContentType == null)
overriddenContentType = MediaType.APPLICATION_FORM_URLENCODED;
Form form = new Form();
for (Map.Entry entry : dataDispatchRequest.getStringTuples().entrySet()) {
@ -143,24 +154,27 @@ public class DataDispatchRequestManager extends RequestManager {
}
if (requestType.equals("POST"))
invocation = requestBuilder.buildPost(Entity.form(form));
invocation = requestBuilder.buildPost(Entity.entity(form, overriddenContentType));
else
invocation = requestBuilder.buildPut(Entity.form(form));
invocation = requestBuilder.buildPut(Entity.entity(form, overriddenContentType));
break;
default:
// Handles raw data types (JSON, Plain text, XML, HTML)
String originalContentType = dataDispatchRequest.getContentType();
if (overriddenContentType == null)
overriddenContentType = originalContentType;
switch (requestType) {
case "POST":
invocation = requestBuilder
.buildPost(Entity.entity(dataDispatchRequest.getBody(), dataDispatchRequest.getContentType()));
.buildPost(Entity.entity(dataDispatchRequest.getBody(), overriddenContentType));
break;
case "PUT":
invocation = requestBuilder
.buildPut(Entity.entity(dataDispatchRequest.getBody(), dataDispatchRequest.getContentType()));
.buildPut(Entity.entity(dataDispatchRequest.getBody(), overriddenContentType));
break;
case "PATCH":
invocation = requestBuilder
.build("PATCH", Entity.entity(dataDispatchRequest.getBody(), dataDispatchRequest.getContentType()));
.build("PATCH", Entity.entity(dataDispatchRequest.getBody(), overriddenContentType));
break;
}
}

View file

@ -16,7 +16,6 @@
package com.rohitawate.everest.requestmanager;
import com.rohitawate.everest.models.requests.EverestRequest;
import com.rohitawate.everest.models.responses.EverestResponse;
import javafx.concurrent.Task;
@ -24,8 +23,8 @@ import javax.ws.rs.core.Response;
public class GETRequestManager extends RequestManager {
public GETRequestManager(EverestRequest request) {
super(request);
GETRequestManager() {
}
@Override
@ -33,9 +32,9 @@ public class GETRequestManager extends RequestManager {
return new Task<EverestResponse>() {
@Override
protected EverestResponse call() throws Exception {
long initialTime = System.currentTimeMillis();
initialTime = System.currentTimeMillis();
Response serverResponse = requestBuilder.get();
response.setTime(initialTime, System.currentTimeMillis());
finalTime = System.currentTimeMillis();
processServerResponse(serverResponse);

View file

@ -34,23 +34,32 @@ import java.util.Map;
public abstract class RequestManager extends Service<EverestResponse> {
private final Client client;
long initialTime;
long finalTime;
EverestRequest request;
EverestResponse response;
Builder requestBuilder;
RequestManager(EverestRequest request) {
RequestManager() {
this.client = initClient();
}
private Client initClient() {
Client client;
client = ClientBuilder.newBuilder()
.register(MultiPartFeature.class)
.build();
// Required for making PATCH requests through Jersey
client.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true);
if (Settings.connectionTimeOutEnable)
client.property(ClientProperties.CONNECT_TIMEOUT, Settings.connectionTimeOut);
if (Settings.connectionReadTimeOutEnable)
client.property(ClientProperties.READ_TIMEOUT, Settings.connectionReadTimeOut);
response = new EverestResponse();
setRequest(request);
return client;
}
public void setRequest(EverestRequest request) {
@ -80,7 +89,10 @@ public abstract class RequestManager extends Service<EverestResponse> {
}
String responseBody = serverResponse.readEntity(String.class);
response = new EverestResponse();
response.setHeaders(serverResponse.getStringHeaders());
response.setTime(initialTime, finalTime);
response.setBody(responseBody);
response.setMediaType(serverResponse.getMediaType());
response.setStatusCode(serverResponse.getStatus());

View file

@ -0,0 +1,94 @@
/*
* 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.requestmanager;
import java.util.LinkedList;
public class RequestManagersPool {
private LinkedList<GETRequestManager> getManagers;
private LinkedList<DataDispatchRequestManager> dataManagers;
private LinkedList<DELETERequestManager> deleteManagers;
public GETRequestManager get() {
if (getManagers == null) {
GETRequestManager newManager = new GETRequestManager();
new Thread(() -> {
getManagers = new LinkedList<>();
getManagers.add(newManager);
}).start();
return newManager;
} else {
for (GETRequestManager getManager : getManagers) {
if (!getManager.isRunning())
return getManager;
}
GETRequestManager newManager = new GETRequestManager();
getManagers.add(newManager);
return newManager;
}
}
public DataDispatchRequestManager data() {
if (dataManagers == null) {
DataDispatchRequestManager newManager = new DataDispatchRequestManager();
new Thread(() -> {
dataManagers = new LinkedList<>();
dataManagers.add(newManager);
}).start();
return newManager;
} else {
for (DataDispatchRequestManager dataManager : dataManagers) {
if (!dataManager.isRunning())
return dataManager;
}
DataDispatchRequestManager newManager = new DataDispatchRequestManager();
dataManagers.add(newManager);
return newManager;
}
}
public DELETERequestManager delete() {
if (deleteManagers == null) {
DELETERequestManager newManager = new DELETERequestManager();
new Thread(() -> {
deleteManagers = new LinkedList<>();
deleteManagers.add(newManager);
}).start();
return newManager;
} else {
for (DELETERequestManager deleteManager : deleteManagers) {
if (!deleteManager.isRunning())
return deleteManager;
}
DELETERequestManager newManager = new DELETERequestManager();
deleteManagers.add(newManager);
return newManager;
}
}
}

View file

@ -19,12 +19,12 @@ package com.rohitawate.everest.util;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDateTime;
public class EverestUtilities {
@ -50,19 +50,15 @@ public class EverestUtilities {
*/
public static void createBugReporter() {
new Thread(() -> {
File bugReporterFile = new File("Everest/BugReporter.jar");
if (!bugReporterFile.exists()) {
InputStream inputStream = EverestUtilities.class.getResourceAsStream("/BugReporter.jar");
Path bugReporter = Paths.get("Everest/BugReporter.jar");
try {
Files.copy(inputStream, bugReporter);
} catch (IOException e) {
e.printStackTrace();
}
Services.loggingService.logInfo("BugReporter was copied to installation folder.", LocalDateTime.now());
} else {
Services.loggingService.logInfo("BugReporter was found.", LocalDateTime.now());
InputStream inputStream = EverestUtilities.class.getResourceAsStream("/BugReporter.jar");
Path bugReporter = Paths.get("Everest/BugReporter.jar");
try {
Files.copy(inputStream, bugReporter, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
e.printStackTrace();
}
Services.loggingService.logInfo("BugReporter was copied to installation folder.", LocalDateTime.now());
}).start();
}
}

View file

@ -18,6 +18,7 @@ package com.rohitawate.everest.util;
import com.google.common.util.concurrent.MoreExecutors;
import com.rohitawate.everest.controllers.HomeWindowController;
import com.rohitawate.everest.requestmanager.RequestManagersPool;
import com.rohitawate.everest.util.history.HistoryManager;
import com.rohitawate.everest.util.logging.Level;
import com.rohitawate.everest.util.logging.LoggingService;
@ -30,12 +31,14 @@ public class Services {
public static LoggingService loggingService;
public static HomeWindowController homeWindowController;
public static Executor singleExecutor;
public static RequestManagersPool pool;
public static void start() {
startServicesThread = new Thread(() -> {
loggingService = new LoggingService(Level.INFO);
historyManager = new HistoryManager();
singleExecutor = MoreExecutors.directExecutor();
pool = new RequestManagersPool();
});
startServicesThread.start();

View file

@ -61,8 +61,8 @@ public class HistoryManager {
/**
* Creates and initializes the database with necessary tables if not already done.
*
* @throws IOException
* @throws SQLException
* @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 {
// Read all queries from Queries.json

View file

@ -17,40 +17,8 @@
package com.rohitawate.everest.util.logging;
class Log {
private Level level;
private String message;
private String time;
private Exception exception;
public Level getLevel() {
return level;
}
public void setLevel(Level level) {
this.level = level;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public Exception getException() {
return exception;
}
public void setException(Exception exception) {
this.exception = exception;
}
Level level;
String message;
String time;
Exception exception;
}

View file

@ -39,15 +39,11 @@ class Logger {
* @param log - The log to be written to file.
*/
synchronized void log(Log log) {
if (log.getLevel().greaterThanEqualTo(this.writerLevel)) {
try {
String logFileContents = readFile(logFilePath);
String logEntry = generateLogEntry(log);
logFileContents = logFileContents.replace("<!-- Placeholder for new log -->", logEntry);
BufferedWriter writer = new BufferedWriter(new FileWriter(logFilePath));
System.out.println(log.message);
if (log.level.greaterThanEqualTo(this.writerLevel)) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(logFilePath, true))) {
writer.flush();
writer.write(logFileContents);
writer.close();
writer.append(getLogEntry(log));
} catch (IOException e) {
e.printStackTrace();
}
@ -63,19 +59,19 @@ class Logger {
* Yellow = Warning
* Green = Info
*/
private String generateLogEntry(Log log) {
private String getLogEntry(Log log) {
String logEntry = this.logEntryTemplate;
logEntry = logEntry.replace("%% LogLevel %%", log.getLevel().toString());
logEntry = logEntry.replace("%% Time %%", log.getTime());
logEntry = logEntry.replace("%% Message %%", log.getMessage());
logEntry = logEntry.replace("%% LogLevel %%", log.level.toString());
logEntry = logEntry.replace("%% Time %%", log.time);
logEntry = logEntry.replace("%% Message %%", log.message);
StringBuilder builder = new StringBuilder();
if (log.getException() != null) {
StackTraceElement[] stackTrace = log.getException().getStackTrace();
builder.append(log.getException().toString());
if (log.exception != null) {
StackTraceElement[] stackTrace = log.exception.getStackTrace();
builder.append(log.exception.toString());
builder.append("<br>\n");
if (stackTrace.length != 0) {
for (StackTraceElement element : log.getException().getStackTrace()) {
for (StackTraceElement element : log.exception.getStackTrace()) {
builder.append(" -- ");
builder.append(element.toString());
builder.append("<br>\n");
@ -129,23 +125,4 @@ class Logger {
return builder.toString();
}
private String readFile(String filePath) {
StringBuilder builder = new StringBuilder();
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
Scanner scanner = new Scanner(bufferedReader);
while (scanner.hasNext()) {
builder.append(scanner.nextLine());
builder.append("\n");
}
scanner.close();
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
return builder.toString();
}
}

View file

@ -24,17 +24,12 @@ import java.time.format.DateTimeFormatter;
public class LoggingService {
private Logger logger;
private DateTimeFormatter dateFormat;
private String message;
private Exception exception;
private LocalDateTime time;
private SevereLogger severeLogger = new SevereLogger();
private WarningLogger warningLogger = new WarningLogger();
private InfoLogger infoLogger = new InfoLogger();
private Log log;
public LoggingService(Level writerLevel) {
logger = new Logger(writerLevel);
dateFormat = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss");
this.log = new Log();
this.logger = new Logger(writerLevel);
this.dateFormat = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss");
}
public void logSevere(String message, Exception exception, LocalDateTime time) {
@ -53,47 +48,23 @@ public class LoggingService {
}
private void setValues(String message, Exception exception, LocalDateTime time) {
this.message = message;
this.exception = exception;
this.time = time;
this.log.message = message;
this.log.exception = exception;
this.log.time = dateFormat.format(time);
}
private class SevereLogger implements Runnable {
@Override
public void run() {
System.out.println(message);
Log log = new Log();
log.setLevel(Level.SEVERE);
log.setMessage(message);
log.setException(exception);
log.setTime(dateFormat.format(time));
logger.log(log);
}
}
private Runnable severeLogger = () -> {
this.log.level = Level.SEVERE;
this.logger.log(this.log);
};
private class WarningLogger implements Runnable {
@Override
public void run() {
System.out.println(message);
Log log = new Log();
log.setLevel(Level.WARNING);
log.setMessage(message);
log.setException(exception);
log.setTime(dateFormat.format(time));
logger.log(log);
}
}
private Runnable warningLogger = () -> {
this.log.level = Level.WARNING;
this.logger.log(log);
};
private class InfoLogger implements Runnable {
@Override
public void run() {
System.out.println(message);
Log log = new Log();
log.setLevel(Level.INFO);
log.setMessage(message);
log.setTime(dateFormat.format(time));
logger.log(log);
}
}
private Runnable infoLogger = () -> {
this.log.level = Level.INFO;
this.logger.log(log);
};
}

View file

@ -31,5 +31,5 @@ public class Settings {
public static int connectionReadTimeOut = 30000;
public static String theme = "Adreana";
public static int showHistoryRange = 3;
public static int showHistoryRange = 7;
}

View file

@ -17,7 +17,6 @@
package com.rohitawate.everest.util.settings;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rohitawate.everest.util.EverestUtilities;
import com.rohitawate.everest.util.Services;
@ -44,8 +43,7 @@ public class SettingsLoader implements Runnable {
System.out.println("Settings file found. Loading settings... ");
ObjectMapper mapper = new ObjectMapper();
nodes = mapper.readTree(settingsFile);
nodes = EverestUtilities.mapper.readTree(settingsFile);
Settings.responseAreaFont = setStringSetting(Settings.responseAreaFont, "responseAreaFont");
Settings.responseAreaFontSize = setIntegerSetting(Settings.responseAreaFontSize, "responseAreaFontSize");
@ -61,7 +59,7 @@ public class SettingsLoader implements Runnable {
Settings.theme = EverestUtilities.trimString(setStringSetting(Settings.theme, "theme"));
Settings.showHistoryRange = setIntegerSetting(Settings.showHistoryRange, "showHistoryRange");
} catch (IOException IOE) {
Services.loggingService.logInfo("Settings file not found. Using defaults", LocalDateTime.now());
Services.loggingService.logInfo("Settings file not found. Using defaults.", LocalDateTime.now());
}
}

View file

@ -27,6 +27,7 @@ import java.util.List;
public class ThemeManager {
private static List<Parent> parentNodes = new ArrayList<>();
private static File themeFile = new File("Everest/themes/" + Settings.theme + ".css");
/**
* Refreshes the theme of all the registered parents by replacing
@ -35,7 +36,6 @@ public class ThemeManager {
*/
public static void refreshTheme() {
if (!Settings.theme.equals("Adreana")) {
File themeFile = new File("Everest/themes/" + Settings.theme + ".css");
if (themeFile.exists()) {
String themePath = themeFile.toURI().toString();
@ -53,7 +53,6 @@ public class ThemeManager {
public static void setTheme(Parent parent) {
if (!Settings.theme.equals("Adreana")) {
File themeFile = new File("Everest/themes/" + Settings.theme + ".css");
if (themeFile.exists()) {
parent.getStylesheets().add(themeFile.toURI().toString());
parentNodes.add(parent);

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

View file

@ -71,6 +71,10 @@
-fx-background-color: #1b1b1b;
}
#copyBodyButton {
-fx-background-color: transparent;
}
#clearResponseAreaButton {
-fx-background-color: #822f2f;
}
@ -312,41 +316,64 @@
-fx-background-color: #2a2a2a;
}
.nonRootTitledPane {
-fx-padding: 3px 0px;
}
.titled-pane .title {
.visualizerLabel {
-fx-font-family: "Liberation Mono", monospace;
-fx-background-color: #404040;
}
.titled-pane .content {
.visualizerRootLabel {
-fx-font-size: 17px;
-fx-text-fill: #dedede;
-fx-font-weight: bold;
}
.visualizerKeyLabel {
-fx-font-size: 17px;
-fx-text-fill: #bababa;
-fx-font-weight: bold;
}
.visualizerValueLabel {
-fx-font-size: 16px;
-fx-text-fill: #959595;
}
/* Visualizer tree */
.tree-view {
-fx-background-color: #353535;
}
.tree-cell .tree-disclosure-node .arrow {
-fx-background-color: orangered;
}
.tree-cell:selected .tree-disclosure-node .arrow,
.tree-cell:focused .tree-disclosure-node .arrow {
-fx-background-color: white;
}
.tree-cell {
-fx-background-color: #282828;
-fx-border-width: 0px;
}
.titled-pane .content {
-fx-font-family: "Liberation Mono", monospace;
-fx-padding: 3px 0px;
.tree-cell:expanded {
-fx-background-color: #454545;
}
.visualizerKeyLabel {
-fx-font-size: 18px;
-fx-text-fill: #bababa;
-fx-text-alignment: left;
.tree-cell:selected,
.tree-cell:focused {
-fx-background-color: cornflowerblue;
}
.visualizerValueLabel {
-fx-font-size: 18px;
-fx-text-fill: #959595;
-fx-text-alignment: left;
.tree-cell:selected .label {
-fx-text-fill: white;
}
.titled-pane .title .text,
.titled-pane .title .arrow-button .arrow {
-fx-background-color: #dadada;
-fx-fill: #dadada;
.tree-view .scroll-bar:horizontal .increment-arrow,
.tree-view .scroll-bar:horizontal .decrement-arrow,
.tree-view .scroll-bar:horizontal .increment-button,
.tree-view .scroll-bar:horizontal .decrement-button {
-fx-padding: 0;
}
/* SnackBar */

View file

@ -16,37 +16,47 @@
~ limitations under the License.
-->
<?import com.jfoenix.controls.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<StackPane fx:id="dashboard" minHeight="720.0" minWidth="1280.0" stylesheets="@../../css/Adreana.css"
xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="com.rohitawate.everest.controllers.DashboardController">
<?import com.jfoenix.controls.JFXButton?>
<?import com.jfoenix.controls.JFXProgressBar?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.Tooltip?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<StackPane fx:id="dashboard" stylesheets="@../../css/Adreana.css" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.rohitawate.everest.controllers.DashboardController">
<children>
<VBox prefHeight="200.0" prefWidth="100.0">
<children>
<HBox alignment="CENTER" maxHeight="100.0" minHeight="100.0" spacing="20.0" VBox.vgrow="ALWAYS">
<children>
<ImageView fitHeight="50.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true"
HBox.hgrow="ALWAYS">
<ImageView fitHeight="50.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true" HBox.hgrow="ALWAYS">
<image>
<Image url="@../../assets/Logo.png"/>
<Image url="@../../assets/Logo.png" />
</image>
</ImageView>
<HBox fx:id="addressSection" alignment="CENTER" maxHeight="40.0" HBox.hgrow="ALWAYS">
<children>
<StackPane fx:id="comboContainer" minHeight="40.0" minWidth="130.0">
<children>
<ComboBox fx:id="httpMethodBox" minHeight="40.0" minWidth="130.0"
StackPane.alignment="CENTER"/>
<ComboBox fx:id="httpMethodBox" minHeight="40.0" minWidth="130.0" StackPane.alignment="CENTER" />
</children>
</StackPane>
<TextField fx:id="addressField" promptText="URL" HBox.hgrow="ALWAYS">
<font>
<Font size="18.0"/>
<Font size="18.0" />
</font>
</TextField>
</children>
@ -59,7 +69,7 @@
<Font size="18.0" />
</font>
<HBox.margin>
<Insets/>
<Insets />
</HBox.margin>
<graphic>
<ImageView fitHeight="15.0" fitWidth="15.0" pickOnBounds="true" preserveRatio="true">
@ -71,16 +81,14 @@
</JFXButton>
</children>
<padding>
<Insets left="20.0" right="20.0"/>
<Insets left="20.0" right="20.0" />
</padding>
</HBox>
<SplitPane dividerPositions="0.1" orientation="VERTICAL" VBox.vgrow="ALWAYS">
<items>
<AnchorPane maxHeight="300.0">
<children>
<TabPane fx:id="requestOptionsTab" minHeight="190.0" tabClosingPolicy="UNAVAILABLE"
tabMinWidth="150.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<TabPane fx:id="requestOptionsTab" minHeight="190.0" tabClosingPolicy="UNAVAILABLE" tabMinWidth="150.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<tabs>
<Tab fx:id="paramsTab" text="PARAMS">
<content>
@ -140,8 +148,7 @@
<children>
<VBox fx:id="responseBox" alignment="CENTER" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<HBox fx:id="responseDetails" alignment="CENTER_RIGHT" maxHeight="50.0"
minHeight="50.0" spacing="30.0" VBox.vgrow="ALWAYS">
<HBox fx:id="responseDetails" alignment="CENTER_RIGHT" maxHeight="50.0" minHeight="50.0" spacing="30.0" VBox.vgrow="ALWAYS">
<children>
<HBox alignment="CENTER_LEFT" HBox.hgrow="ALWAYS">
<children>
@ -162,25 +169,34 @@
</HBox>
<Label fx:id="responseType" text="JSON" textFill="#2dcd2d">
<font>
<Font name="Liberation Mono Bold" size="17.0"/>
<Font name="Liberation Mono Bold" size="17.0" />
</font>
</Label>
<Label fx:id="responseTime" text="151 ms" textFill="WHITE" HBox.hgrow="ALWAYS">
<HBox.margin>
<Insets/>
<Insets />
</HBox.margin>
<font>
<Font name="Liberation Mono" size="17.0"/>
<Font name="Liberation Mono" size="17.0" />
</font>
</Label>
<Label fx:id="responseSize" layoutX="1187.0" layoutY="23.0" text="1998 B" textFill="WHITE" HBox.hgrow="ALWAYS">
<font>
<Font name="Liberation Mono" size="17.0"/>
<Font name="Liberation Mono" size="17.0" />
</font>
<HBox.margin>
<Insets/>
<Insets />
</HBox.margin>
</Label>
<JFXButton fx:id="copyBodyButton" textFill="WHITE">
<graphic>
<ImageView fitHeight="20.0" fitWidth="20.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../assets/Copy.png" />
</image>
</ImageView>
</graphic>
</JFXButton>
<JFXButton fx:id="clearResponseAreaButton" buttonType="RAISED" onAction="#clearResponseArea" ripplerFill="WHITE" text=" CLEAR" textFill="WHITE" HBox.hgrow="ALWAYS">
<graphic>
<ImageView fitHeight="15.0" fitWidth="15.0" pickOnBounds="true" preserveRatio="true">
@ -204,36 +220,22 @@
<tabs>
<Tab closable="false" text="BODY">
<content>
<TextArea fx:id="responseArea" editable="false"
wrapText="true"/>
<TextArea fx:id="responseArea" editable="false" wrapText="true" />
</content>
</Tab>
<Tab fx:id="visualizerTab" closable="false" text="VISUALIZER">
<content>
<ScrollPane fx:id="visualizer" fitToHeight="true"
fitToWidth="true" hbarPolicy="NEVER"/>
</content>
</Tab>
<Tab closable="false" text="HEADERS"/>
<Tab fx:id="visualizerTab" closable="false" text="VISUALIZER" />
<Tab fx:id="responseHeadersTab" closable="false" text="HEADERS" />
</tabs>
</TabPane>
<VBox fx:id="loadingLayer" alignment="CENTER" visible="false">
<VBox fx:id="loadingLayer" alignment="CENTER" spacing="10.0">
<children>
<HBox alignment="CENTER">
<children>
<ImageView fitHeight="150.0" fitWidth="100.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../assets/LoadingCircle_WhiteOnOrange.gif" />
</image>
</ImageView>
<Label text="LOADING" textFill="WHITE">
<font>
<Font size="70.0" />
</font>
</Label>
</children>
</HBox>
<JFXButton fx:id="cancelButton" text=" CANCEL" textFill="WHITE" VBox.vgrow="ALWAYS">
<Label text="LOADING" textFill="WHITE">
<font>
<Font size="70.0" />
</font>
</Label>
<JFXProgressBar fx:id="progressBar" VBox.vgrow="ALWAYS" />
<JFXButton fx:id="cancelButton" text=" CANCEL" textFill="WHITE">
<graphic>
<ImageView fitHeight="15.0" fitWidth="15.0" pickOnBounds="true" preserveRatio="true">
<image>
@ -246,16 +248,14 @@
</VBox>
<VBox fx:id="promptLayer" alignment="CENTER" visible="false">
<children>
<Label text="Enter an address, select a method and hit send."
textFill="WHITE">
<Label text="Enter an address, select a method and hit send." textFill="WHITE">
<font>
<Font size="32.0" />
</font>
</Label>
</children>
</VBox>
<VBox fx:id="errorLayer" alignment="CENTER" layoutX="10.0" layoutY="10.0"
visible="false">
<VBox fx:id="errorLayer" alignment="CENTER" layoutX="10.0" layoutY="10.0" visible="false">
<children>
<ImageView fitHeight="100.0" fitWidth="100.0" opacity="0.75" pickOnBounds="true" preserveRatio="true">
<image>

View file

@ -22,12 +22,12 @@
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.Font?>
<StackPane fx:id="homeWindowSP" stylesheets="@../../css/Adreana.css" xmlns="http://javafx.com/javafx/8.0.111"
<StackPane fx:id="homeWindowSP" stylesheets="@../../css/Adreana.css" xmlns="http://javafx.com/javafx/8.0.141"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.rohitawate.everest.controllers.HomeWindowController">
<children>
<SplitPane fx:id="splitPane" dividerPositions="0.3">
<items>
<VBox fx:id="historyPane" alignment="TOP_CENTER" maxWidth="500.0" minWidth="400.0"
<VBox fx:id="historyPane" alignment="TOP_CENTER" maxWidth="450.0" minWidth="400.0"
SplitPane.resizableWithParent="false">
<children>
<HBox fx:id="historySearchFieldBox" alignment="CENTER" fillHeight="false">

View file

@ -2,5 +2,4 @@
<strong>%% LogLevel %%</strong> %% Time %% <br>
<strong>%% Message %%</strong> <br>
%% StackTrace %%
</p>
<!-- Placeholder for new log -->
</p>

View file

@ -24,7 +24,7 @@
margin: 0px;
background-color: #282828;
font-size: 15px;
font-family: monospace;
font-family: "Liberation Mono", monospace;
}
h1 {
@ -55,6 +55,3 @@
</head>
<body>
<h1>Everest Log: %% Date %%</h1>
<!-- Placeholder for new log -->
</body>
</html>