Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.cooksys.postmaster; import com.cooksys.httpserver.CookieRow; import com.cooksys.httpserver.HeaderRow; import com.cooksys.httpserver.ParsedHttpRequest; import com.cooksys.httpserver.ParsedHttpResponse; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.text.Font; import javafx.scene.text.FontWeight; import javafx.scene.text.Text; import org.apache.http.HttpRequest; /** * * @author Tim Davidson Singleton data model that holds all data shared between * server threads and the javafx GUI. This is a serializable singleton that can * be saved and retrieved from a file */ public class PostmasterModelSingleton implements Serializable { private static transient PostmasterModelSingleton _instance; private static final String POSTMASTER_DATA_FILE = "postmaster.data"; //Data bound from scene private transient ObservableList<String> incomingMessagesList; private transient ObservableList<Text> savedResponsesList; //selected incoming message private transient StringProperty incomingMethod; private transient StringProperty incomingUriPath; private transient ObservableList<String> incomingUriParams; private transient ObservableList<String> incomingHeaders; private transient StringProperty incomingMessageBody; //raw message console private transient StringProperty messageConsole; //we can't serialize StringProperty, so create a String we can serialize private String messageConsoleSerializable; //Shared data private int port; private List<ParsedHttpRequest> requestList; private List<ParsedHttpResponse> responseList; private int defaultResponseIndex; //default constructor public PostmasterModelSingleton() { //initialize properties requestList = new ArrayList<ParsedHttpRequest>(); responseList = new ArrayList<ParsedHttpResponse>(); this.createTransientPropertyInstances(); this.port = 8080; //encode the default response if (responseList.isEmpty()) { ParsedHttpResponse response = new ParsedHttpResponse(); response.setContentType("text/html"); response.getHeaders().add(new HeaderRow("My-Header", "my header value")); response.getHeaders().add(new HeaderRow("Another-Header", "another header value")); response.getCookies().add(new CookieRow("My-Cookie", "my cookie value")); response.setName("Postmaster Default Response"); response.setStatusCode("200 OK"); response.setMessageBody("<html><body><h1>PostMaster Default Response" + "</h1><p>Create your own auto-response message in the 'Saved Responses' tab</p></body></html>"); defaultResponseIndex = 0; //add it to the lists responseList.add(response); Text defaultResponseText = new Text(response.getName()); defaultResponseText.setFont(Font.font(null, FontWeight.BOLD, 12)); savedResponsesList.add(defaultResponseText); } } public void createTransientPropertyInstances() { //instantiate our model objects incomingMessagesList = FXCollections.observableArrayList(); savedResponsesList = FXCollections.observableArrayList(); incomingMethod = new SimpleStringProperty(); incomingUriPath = new SimpleStringProperty(); incomingUriParams = FXCollections.observableArrayList(); incomingHeaders = FXCollections.observableArrayList(); incomingMessageBody = new SimpleStringProperty(); messageConsole = new SimpleStringProperty(); } //singleton method to get current singleton instance //if no instance exists, try to deserialize from the data file //if the file doesn't exist, create a new instance public static PostmasterModelSingleton getInstance() { if (_instance == null) { try { //see if we can read the object from the file first FileInputStream fileInputStream = new FileInputStream(POSTMASTER_DATA_FILE); ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); _instance = (PostmasterModelSingleton) objectInputStream.readObject(); //fill in transient variables from their serializable counterparts _instance.createTransientPropertyInstances(); for (ParsedHttpRequest request : _instance.requestList) { _instance.incomingMessagesList.add(request.getRequestLine()); } int index = 0; for (ParsedHttpResponse response : _instance.responseList) { Text defaultResponseText = new Text(response.getName()); if (index == _instance.defaultResponseIndex) { defaultResponseText.setFont(Font.font(null, FontWeight.BOLD, 12)); } _instance.savedResponsesList.add(defaultResponseText); index++; } _instance.messageConsole.set(_instance.messageConsoleSerializable); } catch (FileNotFoundException ex) { //File does not exist, so create a new instance _instance = new PostmasterModelSingleton(); } catch (IOException | ClassNotFoundException ex) { //for these exceptions, just create a new instance Logger.getLogger(PostmasterModelSingleton.class.getName()).log(Level.SEVERE, null, ex); _instance = new PostmasterModelSingleton(); } } return _instance; } //Serialize the current singleton instance to disk public static void writeToFile() { if (_instance != null) { //make sure there is an instance first File file = new File(POSTMASTER_DATA_FILE); try { //convert messageConsole to serializable format _instance.messageConsoleSerializable = _instance.messageConsole.getValue(); //serialize the object to a file FileOutputStream fileOutputStream = new FileOutputStream(file); ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); objectOutputStream.writeObject(_instance); } catch (FileNotFoundException ex) { Logger.getLogger(PostmasterModelSingleton.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(PostmasterModelSingleton.class.getName()).log(Level.SEVERE, null, ex); } } } // //action methods that server thread calls to notify gui // //Parses the incoming request and updates the GUI public void incomingRequest(HttpRequest request, String messageBody) { //add the new request to the incoming message queue ParsedHttpRequest parsedRequest = ParsedHttpRequest.parseHttpRequest(request, messageBody); this.requestList.add(0, parsedRequest); //add the first line to the listView's list this.incomingMessagesList.add(0, parsedRequest.getRequestLine()); this.updateCurrentIncomingMessage(0); } // //methods to update gui based on selected message // //when user selects a request message, or when one comes in, this method updates //the model with the currently selected message detail public void updateCurrentIncomingMessage(int index) { //get the indexed message from the request list ParsedHttpRequest request = this.requestList.get(index); //set the model properties incomingMethod.set(request.getMethod()); incomingUriPath.set(request.getUriPath()); incomingUriParams.setAll(request.getUriParams()); incomingHeaders.setAll(request.getHeaders()); incomingMessageBody.set(request.getMessageBody()); } //Getters and setters public int getPort() { return port; } public void setPort(int port) { this.port = port; } public ObservableList<String> getIncomingMessagesList() { return incomingMessagesList; } public void setIncomingMessagesList(ObservableList<String> incomingMessagesList) { this.incomingMessagesList = incomingMessagesList; } public List<ParsedHttpRequest> getRequestList() { return requestList; } public void setRequestList(List<ParsedHttpRequest> requestList) { this.requestList = requestList; } public List<ParsedHttpResponse> getResponseList() { return responseList; } public void setResponseList(List<ParsedHttpResponse> responseList) { this.responseList = responseList; } public int getDefaultResponseIndex() { return defaultResponseIndex; } public void setDefaultResponseIndex(int defaultResponseIndex) { this.defaultResponseIndex = defaultResponseIndex; } public StringProperty getMessageConsole() { return messageConsole; } public void setMessageConsole(StringProperty messageConsole) { this.messageConsole = messageConsole; } public StringProperty getIncomingMethod() { return incomingMethod; } public void setIncomingMethod(StringProperty incomingMethod) { this.incomingMethod = incomingMethod; } public StringProperty getIncomingUriPath() { return incomingUriPath; } public void setIncomingUriPath(StringProperty incomingUriPath) { this.incomingUriPath = incomingUriPath; } public ObservableList<String> getIncomingUriParams() { return incomingUriParams; } public void setIncomingUriParams(ObservableList<String> incomingUriParams) { this.incomingUriParams = incomingUriParams; } public ObservableList<String> getIncomingHeaders() { return incomingHeaders; } public void setIncomingHeaders(ObservableList<String> incomingHeaders) { this.incomingHeaders = incomingHeaders; } public StringProperty getIncomingMessageBody() { return incomingMessageBody; } public void setIncomingMessageBody(StringProperty incomingMessageBody) { this.incomingMessageBody = incomingMessageBody; } public ObservableList<Text> getSavedResponsesList() { return savedResponsesList; } public void setSavedResponsesList(ObservableList<Text> savedResponsesList) { this.savedResponsesList = savedResponsesList; } }