001package edu.pdx.cs410J.airlineweb; 002 003import com.google.common.annotations.VisibleForTesting; 004 005import javax.servlet.http.HttpServlet; 006import javax.servlet.http.HttpServletRequest; 007import javax.servlet.http.HttpServletResponse; 008import java.io.IOException; 009import java.io.PrintWriter; 010import java.util.HashMap; 011import java.util.Map; 012 013/** 014 * This servlet ultimately provides a REST API for working with an 015 * <code>Airline</code>. However, in its current state, it is an example 016 * of how to use HTTP and Java servlets to store simple dictionary of words 017 * and their definitions. 018 */ 019public class AirlineServlet extends HttpServlet { 020 static final String WORD_PARAMETER = "word"; 021 static final String DEFINITION_PARAMETER = "definition"; 022 023 private final Map<String, String> dictionary = new HashMap<>(); 024 025 /** 026 * Handles an HTTP GET request from a client by writing the definition of the 027 * word specified in the "word" HTTP parameter to the HTTP response. If the 028 * "word" parameter is not specified, all of the entries in the dictionary 029 * are written to the HTTP response. 030 */ 031 @Override 032 protected void doGet( HttpServletRequest request, HttpServletResponse response ) throws IOException 033 { 034 response.setContentType( "text/plain" ); 035 036 String word = getParameter( WORD_PARAMETER, request ); 037 if (word != null) { 038 writeDefinition(word, response); 039 040 } else { 041 writeAllDictionaryEntries(response); 042 } 043 } 044 045 /** 046 * Handles an HTTP POST request by storing the dictionary entry for the 047 * "word" and "definition" request parameters. It writes the dictionary 048 * entry to the HTTP response. 049 */ 050 @Override 051 protected void doPost( HttpServletRequest request, HttpServletResponse response ) throws IOException 052 { 053 response.setContentType( "text/plain" ); 054 055 String word = getParameter(WORD_PARAMETER, request ); 056 if (word == null) { 057 missingRequiredParameter(response, WORD_PARAMETER); 058 return; 059 } 060 061 String definition = getParameter(DEFINITION_PARAMETER, request ); 062 if ( definition == null) { 063 missingRequiredParameter( response, DEFINITION_PARAMETER ); 064 return; 065 } 066 067 this.dictionary.put(word, definition); 068 069 PrintWriter pw = response.getWriter(); 070 pw.println(Messages.definedWordAs(word, definition)); 071 pw.flush(); 072 073 response.setStatus( HttpServletResponse.SC_OK); 074 } 075 076 /** 077 * Handles an HTTP DELETE request by removing all dictionary entries. This 078 * behavior is exposed for testing purposes only. It's probably not 079 * something that you'd want a real application to expose. 080 */ 081 @Override 082 protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws IOException { 083 response.setContentType("text/plain"); 084 085 this.dictionary.clear(); 086 087 PrintWriter pw = response.getWriter(); 088 pw.println(Messages.allDictionaryEntriesDeleted()); 089 pw.flush(); 090 091 response.setStatus(HttpServletResponse.SC_OK); 092 093 } 094 095 /** 096 * Writes an error message about a missing parameter to the HTTP response. 097 * 098 * The text of the error message is created by {@link Messages#missingRequiredParameter(String)} 099 */ 100 private void missingRequiredParameter( HttpServletResponse response, String parameterName ) 101 throws IOException 102 { 103 String message = Messages.missingRequiredParameter(parameterName); 104 response.sendError(HttpServletResponse.SC_PRECONDITION_FAILED, message); 105 } 106 107 /** 108 * Writes the definition of the given word to the HTTP response. 109 * 110 * The text of the message is formatted with {@link TextDumper} 111 */ 112 private void writeDefinition(String word, HttpServletResponse response) throws IOException { 113 String definition = this.dictionary.get(word); 114 115 if (definition == null) { 116 response.setStatus(HttpServletResponse.SC_NOT_FOUND); 117 118 } else { 119 PrintWriter pw = response.getWriter(); 120 121 Map<String, String> wordDefinition = Map.of(word, definition); 122 TextDumper dumper = new TextDumper(pw); 123 dumper.dump(wordDefinition); 124 125 response.setStatus(HttpServletResponse.SC_OK); 126 } 127 } 128 129 /** 130 * Writes all of the dictionary entries to the HTTP response. 131 * 132 * The text of the message is formatted with {@link TextDumper} 133 */ 134 private void writeAllDictionaryEntries(HttpServletResponse response ) throws IOException 135 { 136 PrintWriter pw = response.getWriter(); 137 TextDumper dumper = new TextDumper(pw); 138 dumper.dump(dictionary); 139 140 response.setStatus( HttpServletResponse.SC_OK ); 141 } 142 143 /** 144 * Returns the value of the HTTP request parameter with the given name. 145 * 146 * @return <code>null</code> if the value of the parameter is 147 * <code>null</code> or is the empty string 148 */ 149 private String getParameter(String name, HttpServletRequest request) { 150 String value = request.getParameter(name); 151 if (value == null || "".equals(value)) { 152 return null; 153 154 } else { 155 return value; 156 } 157 } 158 159 @VisibleForTesting 160 String getDefinition(String word) { 161 return this.dictionary.get(word); 162 } 163}