com.cooksys.postmaster.PostmasterModelSingleton.java Source code

Java tutorial

Introduction

Here is the source code for com.cooksys.postmaster.PostmasterModelSingleton.java

Source

/*
 * 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;
    }
}