Replace dedicated RequestManagers with a single one
This commit is contained in:
parent
2e8cb06cb7
commit
a8413e8b5c
10 changed files with 232 additions and 351 deletions
|
@ -26,7 +26,7 @@ import com.rohitawate.everest.controllers.state.FieldState;
|
||||||
import com.rohitawate.everest.controllers.visualizers.TreeVisualizer;
|
import com.rohitawate.everest.controllers.visualizers.TreeVisualizer;
|
||||||
import com.rohitawate.everest.controllers.visualizers.Visualizer;
|
import com.rohitawate.everest.controllers.visualizers.Visualizer;
|
||||||
import com.rohitawate.everest.exceptions.RedirectException;
|
import com.rohitawate.everest.exceptions.RedirectException;
|
||||||
import com.rohitawate.everest.exceptions.UnreliableResponseException;
|
import com.rohitawate.everest.exceptions.NullResponseException;
|
||||||
import com.rohitawate.everest.format.FormatterFactory;
|
import com.rohitawate.everest.format.FormatterFactory;
|
||||||
import com.rohitawate.everest.logging.LoggingService;
|
import com.rohitawate.everest.logging.LoggingService;
|
||||||
import com.rohitawate.everest.misc.EverestUtilities;
|
import com.rohitawate.everest.misc.EverestUtilities;
|
||||||
|
@ -34,9 +34,9 @@ import com.rohitawate.everest.misc.Services;
|
||||||
import com.rohitawate.everest.misc.ThemeManager;
|
import com.rohitawate.everest.misc.ThemeManager;
|
||||||
import com.rohitawate.everest.models.requests.DELETERequest;
|
import com.rohitawate.everest.models.requests.DELETERequest;
|
||||||
import com.rohitawate.everest.models.requests.DataRequest;
|
import com.rohitawate.everest.models.requests.DataRequest;
|
||||||
|
import com.rohitawate.everest.models.requests.EverestRequest;
|
||||||
import com.rohitawate.everest.models.requests.GETRequest;
|
import com.rohitawate.everest.models.requests.GETRequest;
|
||||||
import com.rohitawate.everest.models.responses.EverestResponse;
|
import com.rohitawate.everest.models.responses.EverestResponse;
|
||||||
import com.rohitawate.everest.requestmanager.DataRequestManager;
|
|
||||||
import com.rohitawate.everest.requestmanager.RequestManager;
|
import com.rohitawate.everest.requestmanager.RequestManager;
|
||||||
import com.rohitawate.everest.requestmanager.RequestManagersPool;
|
import com.rohitawate.everest.requestmanager.RequestManagersPool;
|
||||||
import javafx.beans.binding.Bindings;
|
import javafx.beans.binding.Bindings;
|
||||||
|
@ -239,7 +239,7 @@ public class DashboardController implements Initializable {
|
||||||
getRequest.setTarget(address);
|
getRequest.setTarget(address);
|
||||||
getRequest.setHeaders(headerTabController.getHeaders());
|
getRequest.setHeaders(headerTabController.getHeaders());
|
||||||
|
|
||||||
requestManager = RequestManagersPool.get();
|
requestManager = RequestManagersPool.manager();
|
||||||
requestManager.setRequest(getRequest);
|
requestManager.setRequest(getRequest);
|
||||||
break;
|
break;
|
||||||
case "POST":
|
case "POST":
|
||||||
|
@ -284,7 +284,7 @@ public class DashboardController implements Initializable {
|
||||||
dataRequest.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
dataRequest.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||||
}
|
}
|
||||||
|
|
||||||
requestManager = RequestManagersPool.data();
|
requestManager = RequestManagersPool.manager();
|
||||||
requestManager.setRequest(dataRequest);
|
requestManager.setRequest(dataRequest);
|
||||||
break;
|
break;
|
||||||
case "DELETE":
|
case "DELETE":
|
||||||
|
@ -294,7 +294,7 @@ public class DashboardController implements Initializable {
|
||||||
deleteRequest.setTarget(address);
|
deleteRequest.setTarget(address);
|
||||||
deleteRequest.setHeaders(headerTabController.getHeaders());
|
deleteRequest.setHeaders(headerTabController.getHeaders());
|
||||||
|
|
||||||
requestManager = RequestManagersPool.delete();
|
requestManager = RequestManagersPool.manager();
|
||||||
requestManager.setRequest(deleteRequest);
|
requestManager.setRequest(deleteRequest);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -322,8 +322,8 @@ public class DashboardController implements Initializable {
|
||||||
Exception exception = (Exception) throwable;
|
Exception exception = (Exception) throwable;
|
||||||
LoggingService.logWarning(httpMethodBox.getValue() + " request could not be processed.", exception, LocalDateTime.now());
|
LoggingService.logWarning(httpMethodBox.getValue() + " request could not be processed.", exception, LocalDateTime.now());
|
||||||
|
|
||||||
if (throwable.getClass() == UnreliableResponseException.class) {
|
if (throwable.getClass() == NullResponseException.class) {
|
||||||
UnreliableResponseException URE = (UnreliableResponseException) throwable;
|
NullResponseException URE = (NullResponseException) throwable;
|
||||||
errorTitle.setText(URE.getExceptionTitle());
|
errorTitle.setText(URE.getExceptionTitle());
|
||||||
errorDetails.setText(URE.getExceptionDetails());
|
errorDetails.setText(URE.getExceptionDetails());
|
||||||
} else if (throwable.getClass() == ProcessingException.class) {
|
} else if (throwable.getClass() == ProcessingException.class) {
|
||||||
|
@ -338,7 +338,7 @@ public class DashboardController implements Initializable {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requestManager.getClass() == DataRequestManager.class) {
|
if (requestManager.getRequest().getClass().equals(DataRequest.class)) {
|
||||||
if (throwable.getCause() != null && throwable.getCause().getClass() == IllegalArgumentException.class) {
|
if (throwable.getCause() != null && throwable.getCause().getClass() == IllegalArgumentException.class) {
|
||||||
errorTitle.setText("Did you forget something?");
|
errorTitle.setText("Did you forget something?");
|
||||||
errorDetails.setText("Please specify a body for your " + httpMethodBox.getValue() + " request.");
|
errorDetails.setText("Please specify a body for your " + httpMethodBox.getValue() + " request.");
|
||||||
|
|
|
@ -78,7 +78,7 @@ public class HomeWindowController implements Initializable {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Using LinkedHashMap because they retain order
|
// Using LinkedHashMap because it retains order
|
||||||
tabStateMap = new LinkedHashMap<>();
|
tabStateMap = new LinkedHashMap<>();
|
||||||
recoverState();
|
recoverState();
|
||||||
|
|
||||||
|
@ -199,9 +199,10 @@ public class HomeWindowController implements Initializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeTab(Tab newTab) {
|
private void removeTab(Tab newTab) {
|
||||||
DashboardState closedState = tabStateMap.remove(newTab);
|
DashboardState state = tabStateMap.remove(newTab);
|
||||||
closedState = null;
|
state = null;
|
||||||
tabPane.getTabs().remove(newTab);
|
tabPane.getTabs().remove(newTab);
|
||||||
|
newTab.setOnCloseRequest(null);
|
||||||
newTab = null;
|
newTab = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,11 @@ import com.rohitawate.everest.controllers.DashboardController.ComposerTab;
|
||||||
import com.rohitawate.everest.controllers.DashboardController.ResponseLayer;
|
import com.rohitawate.everest.controllers.DashboardController.ResponseLayer;
|
||||||
import com.rohitawate.everest.controllers.DashboardController.ResponseTab;
|
import com.rohitawate.everest.controllers.DashboardController.ResponseTab;
|
||||||
import com.rohitawate.everest.exceptions.RedirectException;
|
import com.rohitawate.everest.exceptions.RedirectException;
|
||||||
import com.rohitawate.everest.exceptions.UnreliableResponseException;
|
import com.rohitawate.everest.exceptions.NullResponseException;
|
||||||
import com.rohitawate.everest.logging.LoggingService;
|
import com.rohitawate.everest.logging.LoggingService;
|
||||||
|
import com.rohitawate.everest.models.requests.DataRequest;
|
||||||
import com.rohitawate.everest.models.requests.EverestRequest;
|
import com.rohitawate.everest.models.requests.EverestRequest;
|
||||||
import com.rohitawate.everest.models.responses.EverestResponse;
|
import com.rohitawate.everest.models.responses.EverestResponse;
|
||||||
import com.rohitawate.everest.requestmanager.DataRequestManager;
|
|
||||||
import com.rohitawate.everest.requestmanager.RequestManager;
|
import com.rohitawate.everest.requestmanager.RequestManager;
|
||||||
import javafx.event.Event;
|
import javafx.event.Event;
|
||||||
|
|
||||||
|
@ -106,8 +106,8 @@ public class DashboardState {
|
||||||
Exception exception = (Exception) throwable;
|
Exception exception = (Exception) throwable;
|
||||||
LoggingService.logWarning(this.composer.httpMethod + " request could not be processed.", exception, LocalDateTime.now());
|
LoggingService.logWarning(this.composer.httpMethod + " request could not be processed.", exception, LocalDateTime.now());
|
||||||
|
|
||||||
if (throwable.getClass() == UnreliableResponseException.class) {
|
if (throwable.getClass() == NullResponseException.class) {
|
||||||
UnreliableResponseException URE = (UnreliableResponseException) throwable;
|
NullResponseException URE = (NullResponseException) throwable;
|
||||||
errorTitle = URE.getExceptionTitle();
|
errorTitle = URE.getExceptionTitle();
|
||||||
errorDetails = URE.getExceptionDetails();
|
errorDetails = URE.getExceptionDetails();
|
||||||
} else if (throwable.getClass() == ProcessingException.class) {
|
} else if (throwable.getClass() == ProcessingException.class) {
|
||||||
|
@ -131,7 +131,7 @@ public class DashboardState {
|
||||||
errorDetails = "Something went wrong. Try to make another request.Restart Everest if that doesn't work.";
|
errorDetails = "Something went wrong. Try to make another request.Restart Everest if that doesn't work.";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requestManager.getClass() == DataRequestManager.class) {
|
if (requestManager.getRequest().getClass().equals(DataRequest.class)) {
|
||||||
if (throwable.getCause() != null && throwable.getCause().getClass() == IllegalArgumentException.class) {
|
if (throwable.getCause() != null && throwable.getCause().getClass() == IllegalArgumentException.class) {
|
||||||
errorTitle = "Did you forget something?";
|
errorTitle = "Did you forget something?";
|
||||||
errorDetails = "Please specify a body for your " + this.composer.httpMethod + " request.";
|
errorDetails = "Please specify a body for your " + this.composer.httpMethod + " request.";
|
||||||
|
|
|
@ -33,6 +33,7 @@ public class TreeVisualizer extends Visualizer {
|
||||||
public TreeVisualizer() {
|
public TreeVisualizer() {
|
||||||
visualizer = new TreeView<>();
|
visualizer = new TreeView<>();
|
||||||
visualizer.setShowRoot(false);
|
visualizer.setShowRoot(false);
|
||||||
|
visualizer.setCache(true);
|
||||||
setContent(visualizer);
|
setContent(visualizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +63,7 @@ public class TreeVisualizer extends Visualizer {
|
||||||
items.add(new TreeItem<>(i++ + ": " + EverestUtilities.trimString(currentNode.toString())));
|
items.add(new TreeItem<>(i++ + ": " + EverestUtilities.trimString(currentNode.toString())));
|
||||||
} else if (currentNode.isObject()) {
|
} else if (currentNode.isObject()) {
|
||||||
TreeItem<String> newRoot = new TreeItem<>();
|
TreeItem<String> newRoot = new TreeItem<>();
|
||||||
|
newRoot.setExpanded(true);
|
||||||
items.add(newRoot);
|
items.add(newRoot);
|
||||||
populate(newRoot, i++ + ": [Anonymous Object]", currentNode);
|
populate(newRoot, i++ + ": [Anonymous Object]", currentNode);
|
||||||
}
|
}
|
||||||
|
@ -79,6 +81,7 @@ public class TreeVisualizer extends Visualizer {
|
||||||
+ EverestUtilities.trimString(currentNode.toString())));
|
+ EverestUtilities.trimString(currentNode.toString())));
|
||||||
} else if (currentNode.isArray() || currentNode.isObject()) {
|
} else if (currentNode.isArray() || currentNode.isObject()) {
|
||||||
TreeItem<String> newRoot = new TreeItem<>();
|
TreeItem<String> newRoot = new TreeItem<>();
|
||||||
|
newRoot.setExpanded(true);
|
||||||
items.add(newRoot);
|
items.add(newRoot);
|
||||||
populate(newRoot, currentEntry.getKey(), currentNode);
|
populate(newRoot, currentEntry.getKey(), currentNode);
|
||||||
}
|
}
|
||||||
|
@ -90,5 +93,6 @@ public class TreeVisualizer extends Visualizer {
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
visualizer.setRoot(null);
|
visualizer.setRoot(null);
|
||||||
|
System.gc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,11 +21,11 @@ package com.rohitawate.everest.exceptions;
|
||||||
* <p>
|
* <p>
|
||||||
* Used by DashboardController to display ErrorLayer.
|
* Used by DashboardController to display ErrorLayer.
|
||||||
*/
|
*/
|
||||||
public class UnreliableResponseException extends Exception {
|
public class NullResponseException extends Exception {
|
||||||
private String exceptionTitle;
|
private String exceptionTitle;
|
||||||
private String exceptionDetails;
|
private String exceptionDetails;
|
||||||
|
|
||||||
public UnreliableResponseException(String exceptionTitle, String exceptionDetails) {
|
public NullResponseException(String exceptionTitle, String exceptionDetails) {
|
||||||
this.exceptionTitle = exceptionTitle;
|
this.exceptionTitle = exceptionTitle;
|
||||||
this.exceptionDetails = exceptionDetails;
|
this.exceptionDetails = exceptionDetails;
|
||||||
}
|
}
|
|
@ -1,45 +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.requestmanager;
|
|
||||||
|
|
||||||
import com.rohitawate.everest.models.responses.EverestResponse;
|
|
||||||
import javafx.concurrent.Task;
|
|
||||||
|
|
||||||
import javax.ws.rs.ProcessingException;
|
|
||||||
import javax.ws.rs.client.Invocation;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
|
|
||||||
public class DELETERequestManager extends RequestManager {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Task<EverestResponse> createTask() throws ProcessingException {
|
|
||||||
return new Task<EverestResponse>() {
|
|
||||||
@Override
|
|
||||||
protected EverestResponse call() throws Exception {
|
|
||||||
Invocation invocation = requestBuilder.buildDelete();
|
|
||||||
|
|
||||||
initialTime = System.currentTimeMillis();
|
|
||||||
Response serverResponse = invocation.invoke();
|
|
||||||
finalTime = System.currentTimeMillis();
|
|
||||||
|
|
||||||
processServerResponse(serverResponse);
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,181 +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.requestmanager;
|
|
||||||
|
|
||||||
import com.rohitawate.everest.models.requests.DataRequest;
|
|
||||||
import com.rohitawate.everest.models.responses.EverestResponse;
|
|
||||||
import javafx.concurrent.Task;
|
|
||||||
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
|
|
||||||
import org.glassfish.jersey.media.multipart.file.FileDataBodyPart;
|
|
||||||
|
|
||||||
import javax.ws.rs.ProcessingException;
|
|
||||||
import javax.ws.rs.client.Entity;
|
|
||||||
import javax.ws.rs.client.Invocation;
|
|
||||||
import javax.ws.rs.core.Form;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes DataRequest by automatically determining whether it
|
|
||||||
* is a POST, PUT or PATCH request.
|
|
||||||
*/
|
|
||||||
public class DataRequestManager extends RequestManager {
|
|
||||||
private DataRequest dataRequest;
|
|
||||||
private String requestType;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Task<EverestResponse> createTask() throws ProcessingException {
|
|
||||||
return new Task<EverestResponse>() {
|
|
||||||
@Override
|
|
||||||
protected EverestResponse call() throws Exception {
|
|
||||||
dataRequest = (DataRequest) request;
|
|
||||||
requestType = dataRequest.getRequestType();
|
|
||||||
|
|
||||||
Invocation invocation = appendBody();
|
|
||||||
initialTime = System.currentTimeMillis();
|
|
||||||
Response serverResponse = invocation.invoke();
|
|
||||||
finalTime = System.currentTimeMillis();
|
|
||||||
|
|
||||||
processServerResponse(serverResponse);
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the request body based on the content type and generates an invocation.
|
|
||||||
*
|
|
||||||
* @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;
|
|
||||||
|
|
||||||
switch (dataRequest.getContentType()) {
|
|
||||||
case MediaType.MULTIPART_FORM_DATA:
|
|
||||||
FormDataMultiPart formData = new FormDataMultiPart();
|
|
||||||
|
|
||||||
// Adding the string tuples to the request
|
|
||||||
HashMap<String, String> pairs = dataRequest.getStringTuples();
|
|
||||||
for (Map.Entry entry : pairs.entrySet()) {
|
|
||||||
mapEntry = (Map.Entry) entry;
|
|
||||||
formData.field(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
String filePath;
|
|
||||||
File file;
|
|
||||||
boolean fileException = false;
|
|
||||||
String fileExceptionMessage = null;
|
|
||||||
pairs = dataRequest.getFileTuples();
|
|
||||||
|
|
||||||
// Adding the file tuples to the request
|
|
||||||
for (Map.Entry entry : pairs.entrySet()) {
|
|
||||||
mapEntry = (Map.Entry) entry;
|
|
||||||
filePath = mapEntry.getValue();
|
|
||||||
file = new File(filePath);
|
|
||||||
|
|
||||||
if (file.exists())
|
|
||||||
formData.bodyPart(new FileDataBodyPart(mapEntry.getKey(),
|
|
||||||
file, MediaType.APPLICATION_OCTET_STREAM_TYPE));
|
|
||||||
else {
|
|
||||||
fileException = true;
|
|
||||||
// For pretty-printing FileNotFoundException to the UI
|
|
||||||
fileExceptionMessage = " - " + filePath + "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fileException) {
|
|
||||||
throw new FileNotFoundException(fileExceptionMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
formData.setMediaType(MediaType.MULTIPART_FORM_DATA_TYPE);
|
|
||||||
|
|
||||||
if (requestType.equals("POST"))
|
|
||||||
invocation = requestBuilder.buildPost(Entity.entity(formData, MediaType.MULTIPART_FORM_DATA_TYPE));
|
|
||||||
else
|
|
||||||
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 = dataRequest.getBody();
|
|
||||||
|
|
||||||
File check = new File(filePath);
|
|
||||||
|
|
||||||
if (!check.exists()) {
|
|
||||||
throw new FileNotFoundException(filePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
FileInputStream stream = new FileInputStream(filePath);
|
|
||||||
|
|
||||||
if (requestType.equals("POST"))
|
|
||||||
invocation = requestBuilder.buildPost(Entity.entity(stream, overriddenContentType));
|
|
||||||
else
|
|
||||||
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 : dataRequest.getStringTuples().entrySet()) {
|
|
||||||
mapEntry = (Map.Entry) entry;
|
|
||||||
form.param(mapEntry.getKey(), mapEntry.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requestType.equals("POST"))
|
|
||||||
invocation = requestBuilder.buildPost(Entity.entity(form, overriddenContentType));
|
|
||||||
else
|
|
||||||
invocation = requestBuilder.buildPut(Entity.entity(form, overriddenContentType));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// Handles raw data types (JSON, Plain text, XML, HTML)
|
|
||||||
String originalContentType = dataRequest.getContentType();
|
|
||||||
if (overriddenContentType == null)
|
|
||||||
overriddenContentType = originalContentType;
|
|
||||||
switch (requestType) {
|
|
||||||
case "POST":
|
|
||||||
invocation = requestBuilder
|
|
||||||
.buildPost(Entity.entity(dataRequest.getBody(), overriddenContentType));
|
|
||||||
break;
|
|
||||||
case "PUT":
|
|
||||||
invocation = requestBuilder
|
|
||||||
.buildPut(Entity.entity(dataRequest.getBody(), overriddenContentType));
|
|
||||||
break;
|
|
||||||
case "PATCH":
|
|
||||||
invocation = requestBuilder
|
|
||||||
.build("PATCH", Entity.entity(dataRequest.getBody(), overriddenContentType));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return invocation;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,42 +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.requestmanager;
|
|
||||||
|
|
||||||
import com.rohitawate.everest.models.responses.EverestResponse;
|
|
||||||
import javafx.concurrent.Task;
|
|
||||||
|
|
||||||
import javax.ws.rs.ProcessingException;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
|
|
||||||
public class GETRequestManager extends RequestManager {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Task<EverestResponse> createTask() throws ProcessingException {
|
|
||||||
return new Task<EverestResponse>() {
|
|
||||||
@Override
|
|
||||||
protected EverestResponse call() throws Exception {
|
|
||||||
initialTime = System.currentTimeMillis();
|
|
||||||
Response serverResponse = requestBuilder.get();
|
|
||||||
finalTime = System.currentTimeMillis();
|
|
||||||
|
|
||||||
processServerResponse(serverResponse);
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -16,23 +16,55 @@
|
||||||
package com.rohitawate.everest.requestmanager;
|
package com.rohitawate.everest.requestmanager;
|
||||||
|
|
||||||
import com.rohitawate.everest.exceptions.RedirectException;
|
import com.rohitawate.everest.exceptions.RedirectException;
|
||||||
import com.rohitawate.everest.exceptions.UnreliableResponseException;
|
import com.rohitawate.everest.exceptions.NullResponseException;
|
||||||
|
import com.rohitawate.everest.models.requests.DELETERequest;
|
||||||
|
import com.rohitawate.everest.models.requests.DataRequest;
|
||||||
import com.rohitawate.everest.models.requests.EverestRequest;
|
import com.rohitawate.everest.models.requests.EverestRequest;
|
||||||
|
import com.rohitawate.everest.models.requests.GETRequest;
|
||||||
import com.rohitawate.everest.models.responses.EverestResponse;
|
import com.rohitawate.everest.models.responses.EverestResponse;
|
||||||
import com.rohitawate.everest.settings.Settings;
|
import com.rohitawate.everest.settings.Settings;
|
||||||
import javafx.concurrent.Service;
|
import javafx.concurrent.Service;
|
||||||
|
import javafx.concurrent.Task;
|
||||||
import javafx.concurrent.WorkerStateEvent;
|
import javafx.concurrent.WorkerStateEvent;
|
||||||
import javafx.event.EventHandler;
|
import javafx.event.EventHandler;
|
||||||
import org.glassfish.jersey.client.ClientProperties;
|
import org.glassfish.jersey.client.ClientProperties;
|
||||||
import org.glassfish.jersey.client.HttpUrlConnectorProvider;
|
import org.glassfish.jersey.client.HttpUrlConnectorProvider;
|
||||||
|
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
|
||||||
import org.glassfish.jersey.media.multipart.MultiPartFeature;
|
import org.glassfish.jersey.media.multipart.MultiPartFeature;
|
||||||
|
import org.glassfish.jersey.media.multipart.file.FileDataBodyPart;
|
||||||
|
|
||||||
|
import javax.ws.rs.ProcessingException;
|
||||||
import javax.ws.rs.client.Client;
|
import javax.ws.rs.client.Client;
|
||||||
import javax.ws.rs.client.ClientBuilder;
|
import javax.ws.rs.client.ClientBuilder;
|
||||||
|
import javax.ws.rs.client.Entity;
|
||||||
|
import javax.ws.rs.client.Invocation;
|
||||||
import javax.ws.rs.client.Invocation.Builder;
|
import javax.ws.rs.client.Invocation.Builder;
|
||||||
|
import javax.ws.rs.core.Form;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public abstract class RequestManager extends Service<EverestResponse> {
|
/**
|
||||||
|
* Manages all the requests made through Everest.
|
||||||
|
* Converts EverestRequests into JAX-RS Invocations are then processed by Jersey.
|
||||||
|
* Also, parses the response and returns EverestResponses.
|
||||||
|
*
|
||||||
|
* Previously, Everest used separate managers for GET, Data (POST, PUT and PATCH) and DELETE
|
||||||
|
* requests. However, RequestManager extends JavaFX's Service class which is expensive to create objects of.
|
||||||
|
* This made the creation of separate pools for every kind of RequestManager too expensive memory-wise.
|
||||||
|
* Thus, now a single class manages all kinds of Requests thus requiring only a single kind of pool.
|
||||||
|
* Also, this enables us to re-use inactive RequestManagers for all kinds of Requests. For example, previously,
|
||||||
|
* if a GETRequestManager was requested, and all GETRequestManagers were running, a new one would be created even
|
||||||
|
* if a DELETERequestManager was idle.
|
||||||
|
*
|
||||||
|
* TLDR: At the cost of some reduced semantic clarity, the old, separate-for-every-type-of-request RequestManagers
|
||||||
|
* are now replaced by this single works-for-all one to save some serious amount of memory and for better re-use.
|
||||||
|
*/
|
||||||
|
public class RequestManager extends Service<EverestResponse> {
|
||||||
private static final Client client;
|
private static final Client client;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
@ -49,12 +81,46 @@ public abstract class RequestManager extends Service<EverestResponse> {
|
||||||
client.property(ClientProperties.READ_TIMEOUT, Settings.connectionReadTimeOut);
|
client.property(ClientProperties.READ_TIMEOUT, Settings.connectionReadTimeOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
long initialTime;
|
private long initialTime;
|
||||||
long finalTime;
|
private long finalTime;
|
||||||
|
|
||||||
EverestRequest request;
|
private EverestRequest request;
|
||||||
EverestResponse response;
|
private EverestResponse response;
|
||||||
Builder requestBuilder;
|
private Builder requestBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a JavaFX Task for processing the required kind of request.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected Task<EverestResponse> createTask() throws ProcessingException {
|
||||||
|
return new Task<EverestResponse>() {
|
||||||
|
@Override
|
||||||
|
protected EverestResponse call() throws Exception {
|
||||||
|
Response serverResponse = null;
|
||||||
|
|
||||||
|
if (request.getClass().equals(GETRequest.class)) {
|
||||||
|
initialTime = System.currentTimeMillis();
|
||||||
|
serverResponse = requestBuilder.get();
|
||||||
|
finalTime = System.currentTimeMillis();
|
||||||
|
} else if (request.getClass().equals(DataRequest.class)) {
|
||||||
|
DataRequest dataRequest = (DataRequest) request;
|
||||||
|
|
||||||
|
Invocation invocation = appendBody(dataRequest);
|
||||||
|
initialTime = System.currentTimeMillis();
|
||||||
|
serverResponse = invocation.invoke();
|
||||||
|
finalTime = System.currentTimeMillis();
|
||||||
|
} else if (request.getClass().equals(DELETERequest.class)) {
|
||||||
|
initialTime = System.currentTimeMillis();
|
||||||
|
serverResponse = requestBuilder.delete();
|
||||||
|
finalTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
processServerResponse(serverResponse);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public void setRequest(EverestRequest request) {
|
public void setRequest(EverestRequest request) {
|
||||||
this.request = request;
|
this.request = request;
|
||||||
|
@ -71,10 +137,14 @@ public abstract class RequestManager extends Service<EverestResponse> {
|
||||||
requestBuilder.header("User-Agent", "Everest");
|
requestBuilder.header("User-Agent", "Everest");
|
||||||
}
|
}
|
||||||
|
|
||||||
void processServerResponse(Response serverResponse)
|
/**
|
||||||
throws UnreliableResponseException, RedirectException {
|
* Takes a ServerResponse and extracts all the headers, the body, the response time and other details
|
||||||
|
* into a EverestResponse.
|
||||||
|
*/
|
||||||
|
private void processServerResponse(Response serverResponse)
|
||||||
|
throws NullResponseException, RedirectException {
|
||||||
if (serverResponse == null) {
|
if (serverResponse == null) {
|
||||||
throw new UnreliableResponseException("The server did not respond.",
|
throw new NullResponseException("The server did not respond.",
|
||||||
"Like that crush from high school..");
|
"Like that crush from high school..");
|
||||||
} else if (serverResponse.getStatus() == 301 || serverResponse.getStatus() == 302) {
|
} else if (serverResponse.getStatus() == 301 || serverResponse.getStatus() == 302) {
|
||||||
throw new RedirectException(
|
throw new RedirectException(
|
||||||
|
@ -108,4 +178,122 @@ public abstract class RequestManager extends Service<EverestResponse> {
|
||||||
removeEventHandler(WorkerStateEvent.WORKER_STATE_FAILED, getOnFailed());
|
removeEventHandler(WorkerStateEvent.WORKER_STATE_FAILED, getOnFailed());
|
||||||
removeEventHandler(WorkerStateEvent.WORKER_STATE_CANCELLED, getOnCancelled());
|
removeEventHandler(WorkerStateEvent.WORKER_STATE_CANCELLED, getOnCancelled());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the request body based on the content type and generates an invocation.
|
||||||
|
* Used for DataRequests.
|
||||||
|
*
|
||||||
|
* @return invocation object
|
||||||
|
*/
|
||||||
|
private Invocation appendBody(DataRequest dataRequest) 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;
|
||||||
|
String requestType = dataRequest.getRequestType();
|
||||||
|
|
||||||
|
switch (dataRequest.getContentType()) {
|
||||||
|
case MediaType.MULTIPART_FORM_DATA:
|
||||||
|
FormDataMultiPart formData = new FormDataMultiPart();
|
||||||
|
|
||||||
|
// Adding the string tuples to the request
|
||||||
|
HashMap<String, String> pairs = dataRequest.getStringTuples();
|
||||||
|
for (Map.Entry entry : pairs.entrySet()) {
|
||||||
|
mapEntry = (Map.Entry) entry;
|
||||||
|
formData.field(mapEntry.getKey(), mapEntry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
String filePath;
|
||||||
|
File file;
|
||||||
|
boolean fileException = false;
|
||||||
|
String fileExceptionMessage = null;
|
||||||
|
pairs = dataRequest.getFileTuples();
|
||||||
|
|
||||||
|
// Adding the file tuples to the request
|
||||||
|
for (Map.Entry entry : pairs.entrySet()) {
|
||||||
|
mapEntry = (Map.Entry) entry;
|
||||||
|
filePath = mapEntry.getValue();
|
||||||
|
file = new File(filePath);
|
||||||
|
|
||||||
|
if (file.exists())
|
||||||
|
formData.bodyPart(new FileDataBodyPart(mapEntry.getKey(),
|
||||||
|
file, MediaType.APPLICATION_OCTET_STREAM_TYPE));
|
||||||
|
else {
|
||||||
|
fileException = true;
|
||||||
|
// For pretty-printing FileNotFoundException to the UI
|
||||||
|
fileExceptionMessage = " - " + filePath + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileException) {
|
||||||
|
throw new FileNotFoundException(fileExceptionMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
formData.setMediaType(MediaType.MULTIPART_FORM_DATA_TYPE);
|
||||||
|
|
||||||
|
if (requestType.equals("POST"))
|
||||||
|
invocation = requestBuilder.buildPost(Entity.entity(formData, MediaType.MULTIPART_FORM_DATA_TYPE));
|
||||||
|
else
|
||||||
|
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 = dataRequest.getBody();
|
||||||
|
|
||||||
|
File check = new File(filePath);
|
||||||
|
|
||||||
|
if (!check.exists()) {
|
||||||
|
throw new FileNotFoundException(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
FileInputStream stream = new FileInputStream(filePath);
|
||||||
|
|
||||||
|
if (requestType.equals("POST"))
|
||||||
|
invocation = requestBuilder.buildPost(Entity.entity(stream, overriddenContentType));
|
||||||
|
else
|
||||||
|
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 : dataRequest.getStringTuples().entrySet()) {
|
||||||
|
mapEntry = (Map.Entry) entry;
|
||||||
|
form.param(mapEntry.getKey(), mapEntry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requestType.equals("POST"))
|
||||||
|
invocation = requestBuilder.buildPost(Entity.entity(form, overriddenContentType));
|
||||||
|
else
|
||||||
|
invocation = requestBuilder.buildPut(Entity.entity(form, overriddenContentType));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Handles raw data types (JSON, Plain text, XML, HTML)
|
||||||
|
String originalContentType = dataRequest.getContentType();
|
||||||
|
if (overriddenContentType == null)
|
||||||
|
overriddenContentType = originalContentType;
|
||||||
|
switch (requestType) {
|
||||||
|
case "POST":
|
||||||
|
invocation = requestBuilder
|
||||||
|
.buildPost(Entity.entity(dataRequest.getBody(), overriddenContentType));
|
||||||
|
break;
|
||||||
|
case "PUT":
|
||||||
|
invocation = requestBuilder
|
||||||
|
.buildPut(Entity.entity(dataRequest.getBody(), overriddenContentType));
|
||||||
|
break;
|
||||||
|
case "PATCH":
|
||||||
|
invocation = requestBuilder
|
||||||
|
.build("PATCH", Entity.entity(dataRequest.getBody(), overriddenContentType));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return invocation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,70 +19,26 @@ package com.rohitawate.everest.requestmanager;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the various RequestManagers employed by Everest.
|
* Provides a dynamically-growing pool RequestManagers used by Everest.
|
||||||
* <p>
|
* <p>
|
||||||
* Pools are created as needed i.e. the first DELETE request
|
* The manager() method when invoked, searches the pool linearly.
|
||||||
* will create the pool of DELETERequestManagers. If a DELETE
|
|
||||||
* request is never made, the pool won't be created. Same applies
|
|
||||||
* for all other types of requests.
|
|
||||||
* <p>
|
|
||||||
* When demanding a RequestManager, the pool is checked linearly.
|
|
||||||
* The first RequestManager which is not currently running will be
|
* The first RequestManager which is not currently running will be
|
||||||
* returned to the caller. If all the managers in the pool are running,
|
* returned to the caller. If all the managers in the pool are running,
|
||||||
* a new one is created, added to the pool, and returned.
|
* a new one will be created, added to the pool, and returned.
|
||||||
*/
|
*/
|
||||||
public class RequestManagersPool {
|
public class RequestManagersPool {
|
||||||
private static ArrayList<GETRequestManager> getManagers;
|
private static ArrayList<RequestManager> pool = new ArrayList<>();
|
||||||
private static ArrayList<DataRequestManager> dataManagers;
|
|
||||||
private static ArrayList<DELETERequestManager> deleteManagers;
|
|
||||||
|
|
||||||
public static GETRequestManager get() {
|
public static RequestManager manager() {
|
||||||
if (getManagers == null)
|
for (RequestManager manager: pool) {
|
||||||
getManagers = new ArrayList<>();
|
if (!manager.isRunning()) {
|
||||||
|
manager.reset();
|
||||||
for (GETRequestManager getManager : getManagers) {
|
return manager;
|
||||||
if (!getManager.isRunning()) {
|
|
||||||
getManager.reset();
|
|
||||||
return getManager;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GETRequestManager newManager = new GETRequestManager();
|
RequestManager newManager = new RequestManager();
|
||||||
getManagers.add(newManager);
|
pool.add(newManager);
|
||||||
|
|
||||||
return newManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DataRequestManager data() {
|
|
||||||
if (dataManagers == null)
|
|
||||||
dataManagers = new ArrayList<>();
|
|
||||||
|
|
||||||
for (DataRequestManager dataManager : dataManagers) {
|
|
||||||
if (!dataManager.isRunning()) {
|
|
||||||
dataManager.reset();
|
|
||||||
return dataManager;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DataRequestManager newManager = new DataRequestManager();
|
|
||||||
dataManagers.add(newManager);
|
|
||||||
|
|
||||||
return newManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DELETERequestManager delete() {
|
|
||||||
if (deleteManagers == null)
|
|
||||||
deleteManagers = new ArrayList<>();
|
|
||||||
|
|
||||||
for (DELETERequestManager deleteManager : deleteManagers) {
|
|
||||||
if (!deleteManager.isRunning()) {
|
|
||||||
deleteManager.reset();
|
|
||||||
return deleteManager;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DELETERequestManager newManager = new DELETERequestManager();
|
|
||||||
deleteManagers.add(newManager);
|
|
||||||
|
|
||||||
return newManager;
|
return newManager;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue