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.Visualizer;
|
||||
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.logging.LoggingService;
|
||||
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.models.requests.DELETERequest;
|
||||
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.responses.EverestResponse;
|
||||
import com.rohitawate.everest.requestmanager.DataRequestManager;
|
||||
import com.rohitawate.everest.requestmanager.RequestManager;
|
||||
import com.rohitawate.everest.requestmanager.RequestManagersPool;
|
||||
import javafx.beans.binding.Bindings;
|
||||
|
@ -239,7 +239,7 @@ public class DashboardController implements Initializable {
|
|||
getRequest.setTarget(address);
|
||||
getRequest.setHeaders(headerTabController.getHeaders());
|
||||
|
||||
requestManager = RequestManagersPool.get();
|
||||
requestManager = RequestManagersPool.manager();
|
||||
requestManager.setRequest(getRequest);
|
||||
break;
|
||||
case "POST":
|
||||
|
@ -284,7 +284,7 @@ public class DashboardController implements Initializable {
|
|||
dataRequest.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||
}
|
||||
|
||||
requestManager = RequestManagersPool.data();
|
||||
requestManager = RequestManagersPool.manager();
|
||||
requestManager.setRequest(dataRequest);
|
||||
break;
|
||||
case "DELETE":
|
||||
|
@ -294,7 +294,7 @@ public class DashboardController implements Initializable {
|
|||
deleteRequest.setTarget(address);
|
||||
deleteRequest.setHeaders(headerTabController.getHeaders());
|
||||
|
||||
requestManager = RequestManagersPool.delete();
|
||||
requestManager = RequestManagersPool.manager();
|
||||
requestManager.setRequest(deleteRequest);
|
||||
break;
|
||||
default:
|
||||
|
@ -322,8 +322,8 @@ public class DashboardController implements Initializable {
|
|||
Exception exception = (Exception) throwable;
|
||||
LoggingService.logWarning(httpMethodBox.getValue() + " request could not be processed.", exception, LocalDateTime.now());
|
||||
|
||||
if (throwable.getClass() == UnreliableResponseException.class) {
|
||||
UnreliableResponseException URE = (UnreliableResponseException) throwable;
|
||||
if (throwable.getClass() == NullResponseException.class) {
|
||||
NullResponseException URE = (NullResponseException) throwable;
|
||||
errorTitle.setText(URE.getExceptionTitle());
|
||||
errorDetails.setText(URE.getExceptionDetails());
|
||||
} else if (throwable.getClass() == ProcessingException.class) {
|
||||
|
@ -338,7 +338,7 @@ public class DashboardController implements Initializable {
|
|||
return;
|
||||
}
|
||||
|
||||
if (requestManager.getClass() == DataRequestManager.class) {
|
||||
if (requestManager.getRequest().getClass().equals(DataRequest.class)) {
|
||||
if (throwable.getCause() != null && throwable.getCause().getClass() == IllegalArgumentException.class) {
|
||||
errorTitle.setText("Did you forget something?");
|
||||
errorDetails.setText("Please specify a body for your " + httpMethodBox.getValue() + " request.");
|
||||
|
|
|
@ -78,7 +78,7 @@ public class HomeWindowController implements Initializable {
|
|||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// Using LinkedHashMap because they retain order
|
||||
// Using LinkedHashMap because it retains order
|
||||
tabStateMap = new LinkedHashMap<>();
|
||||
recoverState();
|
||||
|
||||
|
@ -199,9 +199,10 @@ public class HomeWindowController implements Initializable {
|
|||
}
|
||||
|
||||
private void removeTab(Tab newTab) {
|
||||
DashboardState closedState = tabStateMap.remove(newTab);
|
||||
closedState = null;
|
||||
DashboardState state = tabStateMap.remove(newTab);
|
||||
state = null;
|
||||
tabPane.getTabs().remove(newTab);
|
||||
newTab.setOnCloseRequest(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.ResponseTab;
|
||||
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.models.requests.DataRequest;
|
||||
import com.rohitawate.everest.models.requests.EverestRequest;
|
||||
import com.rohitawate.everest.models.responses.EverestResponse;
|
||||
import com.rohitawate.everest.requestmanager.DataRequestManager;
|
||||
import com.rohitawate.everest.requestmanager.RequestManager;
|
||||
import javafx.event.Event;
|
||||
|
||||
|
@ -106,8 +106,8 @@ public class DashboardState {
|
|||
Exception exception = (Exception) throwable;
|
||||
LoggingService.logWarning(this.composer.httpMethod + " request could not be processed.", exception, LocalDateTime.now());
|
||||
|
||||
if (throwable.getClass() == UnreliableResponseException.class) {
|
||||
UnreliableResponseException URE = (UnreliableResponseException) throwable;
|
||||
if (throwable.getClass() == NullResponseException.class) {
|
||||
NullResponseException URE = (NullResponseException) throwable;
|
||||
errorTitle = URE.getExceptionTitle();
|
||||
errorDetails = URE.getExceptionDetails();
|
||||
} 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.";
|
||||
}
|
||||
|
||||
if (requestManager.getClass() == DataRequestManager.class) {
|
||||
if (requestManager.getRequest().getClass().equals(DataRequest.class)) {
|
||||
if (throwable.getCause() != null && throwable.getCause().getClass() == IllegalArgumentException.class) {
|
||||
errorTitle = "Did you forget something?";
|
||||
errorDetails = "Please specify a body for your " + this.composer.httpMethod + " request.";
|
||||
|
|
|
@ -33,6 +33,7 @@ public class TreeVisualizer extends Visualizer {
|
|||
public TreeVisualizer() {
|
||||
visualizer = new TreeView<>();
|
||||
visualizer.setShowRoot(false);
|
||||
visualizer.setCache(true);
|
||||
setContent(visualizer);
|
||||
}
|
||||
|
||||
|
@ -62,6 +63,7 @@ public class TreeVisualizer extends Visualizer {
|
|||
items.add(new TreeItem<>(i++ + ": " + EverestUtilities.trimString(currentNode.toString())));
|
||||
} else if (currentNode.isObject()) {
|
||||
TreeItem<String> newRoot = new TreeItem<>();
|
||||
newRoot.setExpanded(true);
|
||||
items.add(newRoot);
|
||||
populate(newRoot, i++ + ": [Anonymous Object]", currentNode);
|
||||
}
|
||||
|
@ -79,6 +81,7 @@ public class TreeVisualizer extends Visualizer {
|
|||
+ EverestUtilities.trimString(currentNode.toString())));
|
||||
} else if (currentNode.isArray() || currentNode.isObject()) {
|
||||
TreeItem<String> newRoot = new TreeItem<>();
|
||||
newRoot.setExpanded(true);
|
||||
items.add(newRoot);
|
||||
populate(newRoot, currentEntry.getKey(), currentNode);
|
||||
}
|
||||
|
@ -90,5 +93,6 @@ public class TreeVisualizer extends Visualizer {
|
|||
|
||||
public void clear() {
|
||||
visualizer.setRoot(null);
|
||||
System.gc();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,11 +21,11 @@ package com.rohitawate.everest.exceptions;
|
|||
* <p>
|
||||
* Used by DashboardController to display ErrorLayer.
|
||||
*/
|
||||
public class UnreliableResponseException extends Exception {
|
||||
public class NullResponseException extends Exception {
|
||||
private String exceptionTitle;
|
||||
private String exceptionDetails;
|
||||
|
||||
public UnreliableResponseException(String exceptionTitle, String exceptionDetails) {
|
||||
public NullResponseException(String exceptionTitle, String exceptionDetails) {
|
||||
this.exceptionTitle = exceptionTitle;
|
||||
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;
|
||||
|
||||
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.GETRequest;
|
||||
import com.rohitawate.everest.models.responses.EverestResponse;
|
||||
import com.rohitawate.everest.settings.Settings;
|
||||
import javafx.concurrent.Service;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.concurrent.WorkerStateEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import org.glassfish.jersey.client.ClientProperties;
|
||||
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.file.FileDataBodyPart;
|
||||
|
||||
import javax.ws.rs.ProcessingException;
|
||||
import javax.ws.rs.client.Client;
|
||||
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.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;
|
||||
|
||||
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;
|
||||
|
||||
static {
|
||||
|
@ -49,12 +81,46 @@ public abstract class RequestManager extends Service<EverestResponse> {
|
|||
client.property(ClientProperties.READ_TIMEOUT, Settings.connectionReadTimeOut);
|
||||
}
|
||||
|
||||
long initialTime;
|
||||
long finalTime;
|
||||
private long initialTime;
|
||||
private long finalTime;
|
||||
|
||||
EverestRequest request;
|
||||
EverestResponse response;
|
||||
Builder requestBuilder;
|
||||
private EverestRequest request;
|
||||
private EverestResponse response;
|
||||
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) {
|
||||
this.request = request;
|
||||
|
@ -71,10 +137,14 @@ public abstract class RequestManager extends Service<EverestResponse> {
|
|||
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) {
|
||||
throw new UnreliableResponseException("The server did not respond.",
|
||||
throw new NullResponseException("The server did not respond.",
|
||||
"Like that crush from high school..");
|
||||
} else if (serverResponse.getStatus() == 301 || serverResponse.getStatus() == 302) {
|
||||
throw new RedirectException(
|
||||
|
@ -108,4 +178,122 @@ public abstract class RequestManager extends Service<EverestResponse> {
|
|||
removeEventHandler(WorkerStateEvent.WORKER_STATE_FAILED, getOnFailed());
|
||||
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;
|
||||
|
||||
/**
|
||||
* Provides the various RequestManagers employed by Everest.
|
||||
* Provides a dynamically-growing pool RequestManagers used by Everest.
|
||||
* <p>
|
||||
* Pools are created as needed i.e. the first DELETE request
|
||||
* 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 manager() method when invoked, searches the pool linearly.
|
||||
* The first RequestManager which is not currently running will be
|
||||
* 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 {
|
||||
private static ArrayList<GETRequestManager> getManagers;
|
||||
private static ArrayList<DataRequestManager> dataManagers;
|
||||
private static ArrayList<DELETERequestManager> deleteManagers;
|
||||
private static ArrayList<RequestManager> pool = new ArrayList<>();
|
||||
|
||||
public static GETRequestManager get() {
|
||||
if (getManagers == null)
|
||||
getManagers = new ArrayList<>();
|
||||
|
||||
for (GETRequestManager getManager : getManagers) {
|
||||
if (!getManager.isRunning()) {
|
||||
getManager.reset();
|
||||
return getManager;
|
||||
public static RequestManager manager() {
|
||||
for (RequestManager manager: pool) {
|
||||
if (!manager.isRunning()) {
|
||||
manager.reset();
|
||||
return manager;
|
||||
}
|
||||
}
|
||||
|
||||
GETRequestManager newManager = new GETRequestManager();
|
||||
getManagers.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);
|
||||
RequestManager newManager = new RequestManager();
|
||||
pool.add(newManager);
|
||||
|
||||
return newManager;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue