|
CSCI A348/548
|
3. Handling the Client Request: Form Data
package coreservlets;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
/** Simple servlet that reads three parameters from the
* form data.
* <P>
* Taken from Core Servlets and JavaServer Pages
* from Prentice Hall and Sun Microsystems Press,
* http://www.coreservlets.com/.
* © 2000 Marty Hall; may be freely used or adapted.
*/
public class ThreeParams extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "Reading Three Request Parameters";
out.println(ServletUtilities.headWithTitle(title) +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H1 ALIGN=CENTER>" + title + "</H1>\n" +
"<UL>\n" +
" <LI><B>param1</B>: "
+ request.getParameter("param1") + "\n" +
" <LI><B>param2</B>: "
+ request.getParameter("param2") + "\n" +
" <LI><B>param3</B>: "
+ request.getParameter("param3") + "\n" +
"</UL>\n" +
"</BODY></HTML>");
}
}
You can use a form to access the servlet, but you don't have to. See what I mean by looking at this invocation (or this one).
So you get the idea. (A CGI.pm sort of thing).
Here's how you display all parameters:
package coreservlets;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
/** Shows all the parameters sent to the servlet via either
* GET or POST. Specially marks parameters that have
* no values or multiple values.
* <P>
* Taken from Core Servlets and JavaServer Pages
* from Prentice Hall and Sun Microsystems Press,
* http://www.coreservlets.com/.
* © 2000 Marty Hall; may be freely used or adapted.
*/
public class ShowParameters extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "Reading All Request Parameters";
out.println(ServletUtilities.headWithTitle(title) +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H1 ALIGN=CENTER>" + title + "</H1>\n" +
"<TABLE BORDER=1 ALIGN=CENTER>\n" +
"<TR BGCOLOR=\"#FFAD00\">\n" +
"<TH>Parameter Name<TH>Parameter Value(s)");
Enumeration paramNames = request.getParameterNames();
while(paramNames.hasMoreElements()) {
String paramName = (String)paramNames.nextElement();
out.print("<TR><TD>" + paramName + "\n<TD>");
String[] paramValues =
request.getParameterValues(paramName);
if (paramValues.length == 1) {
String paramValue = paramValues[0];
if (paramValue.length() == 0)
out.println("<I>No Value</I>");
else
out.println(paramValue);
} else {
out.println("<UL>");
for(int i=0; i<paramValues.length; i++) {
out.println("<LI>" + paramValues[i]);
}
out.println("</UL>");
}
}
out.println("</TABLE>\n</BODY></HTML>");
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
Remember that compiling into a package is done like this:
Again, you could use a form, but no need to.javac -d . ShowParameters.java
Here are some examples: one, two, three. I personally think this is nifty.
Resume processing servlet. This application has three parts.
First, a front end, named SubmitResume.html that you place in
(You will access the file from your$coreServlets/../../SubmitResume.html
:21xxx/SubmitResume.html Tomcat address). Here's the HTML file:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!--
Front end to servlet that handles previewing and storing resumes
submitted by job applicants.
Taken from Core Servlets and JavaServer Pages
from Prentice Hall and Sun Microsystems Press,
http://www.coreservlets.com/.
© 2000 Marty Hall; may be freely used or adapted.
-->
<HTML>
<HEAD>
<TITLE>Free Resume Posting</TITLE>
<LINK REL=STYLESHEET
HREF="jobs-site-styles.css"
TYPE="text/css">
</HEAD>
<BODY>
<H1>hotcomputerjobs.com</H1>
<P CLASS="LARGER">
To use our <I>free</I> resume-posting service, simply fill
out the brief summary of your skills below. Use "Preview"
to check the results, then press "Submit" once it is
ready. Your mini resume will appear on-line within 24 hours.</P>
<HR>
<FORM ACTION="/servlet/coreservlets.SubmitResume"
METHOD="POST">
<DL>
<DT><B>First, give some general information about the look of
your resume:</B>
<DD>Heading font:
<INPUT TYPE="TEXT" NAME="headingFont" VALUE="default">
<DD>Heading text size:
<INPUT TYPE="TEXT" NAME="headingSize" VALUE=32>
<DD>Body font:
<INPUT TYPE="TEXT" NAME="bodyFont" VALUE="default">
<DD>Body text size:
<INPUT TYPE="TEXT" NAME="bodySize" VALUE=18>
<DD>Foreground color:
<INPUT TYPE="TEXT" NAME="fgColor" VALUE="BLACK">
<DD>Background color:
<INPUT TYPE="TEXT" NAME="bgColor" VALUE="WHITE">
<DT><B>Next, give some general information about yourself:</B>
<DD>Name: <INPUT TYPE="TEXT" NAME="name">
<DD>Current or most recent title:
<INPUT TYPE="TEXT" NAME="title">
<DD>Email address: <INPUT TYPE="TEXT" NAME="email">
<DD>Programming Languages:
<INPUT TYPE="TEXT" NAME="languages">
<DT><B>Finally, enter a brief summary of your skills and
experience:</B> (use <P> to separate paragraphs.
Other HTML markup is also permitted.)
<DD><TEXTAREA NAME="skills"
ROWS=15 COLS=60 WRAP="SOFT"></TEXTAREA>
</DL>
<CENTER>
<INPUT TYPE="SUBMIT" NAME="previewButton" Value="Preview">
<INPUT TYPE="SUBMIT" NAME="submitButton" Value="Submit">
</CENTER>
</FORM>
<HR>
<P CLASS="TINY">See our privacy policy
<A HREF="we-will-spam-you.html">here</A>.</P>
</BODY>
</HTML>
Note one thing: it uses a cascading style sheet, that you need to create in
Here's the file:$coreServlets/../../jobs-site-styles.css
<STYLE TYPE="text/css">
<!--
BODY { background-color: WHITE }
H1 { color: BLUE;
text-align: center;
font-size: 36px;
font-family: Arial Black, Arial, Helvetica, sans-serif
}
.LARGER { font-size: 120% }
.TINY { font-size: 50% }
H2 { color: #440000;
text-align: left;
font-family: Arial, Helvetica, sans-serif
}
H3 { color: #440000;
text-align: left;
font-family: Arial, Helvetica, sans-serif
}
UL { margin-top: 0;
border-top-width: 0;
padding-top: 0
}
PRE { font-size: 105%;
}
CODE { font-size: 105%;
}
.TOC { font-size: 90%;
font-weight: bold;
font-family: Arial, Helvetica, sans-serif
}
TH.COLORED { background-color: #FFAD00
}
TR.COLORED { background-color: #FFAD00
}
TH.TITLE { background-color: #EF8429;
font-size: 40px;
font-family: Arial, Helvetica, sans-serif;
}
A:hover { color: red }
-->
</STYLE>
You also need a servlet:
package coreservlets;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
/** Servlet that handles previewing and storing resumes
* submitted by job applicants.
* <P>
* Taken from Core Servlets and JavaServer Pages
* from Prentice Hall and Sun Microsystems Press,
* http://www.coreservlets.com/.
* © 2000 Marty Hall; may be freely used or adapted.
*/
public class SubmitResume extends HttpServlet {
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
if (request.getParameter("previewButton") != null) {
showPreview(request, out);
} else {
storeResume(request);
showConfirmation(request, out);
}
}
// Shows a preview of the submitted resume. Takes
// the font information and builds an HTML
// style sheet out of it, then takes the real
// resume information and presents it formatted with
// that style sheet.
private void showPreview(HttpServletRequest request,
PrintWriter out) {
String headingFont = request.getParameter("headingFont");
headingFont = replaceIfMissingOrDefault(headingFont, "");
int headingSize =
getSize(request.getParameter("headingSize"), 32);
String bodyFont = request.getParameter("bodyFont");
bodyFont = replaceIfMissingOrDefault(bodyFont, "");
int bodySize =
getSize(request.getParameter("bodySize"), 18);
String fgColor = request.getParameter("fgColor");
fgColor = replaceIfMissing(fgColor, "BLACK");
String bgColor = request.getParameter("bgColor");
bgColor = replaceIfMissing(bgColor, "WHITE");
String name = request.getParameter("name");
name = replaceIfMissing(name, "Lou Zer");
String title = request.getParameter("title");
title = replaceIfMissing(title, "Loser");
String email = request.getParameter("email");
email =
replaceIfMissing(email, "contact@hotcomputerjobs.com");
String languages = request.getParameter("languages");
languages = replaceIfMissing(languages, "<I>None</I>");
String languageList = makeList(languages);
String skills = request.getParameter("skills");
skills = replaceIfMissing(skills, "Not many, obviously.");
out.println
(ServletUtilities.DOCTYPE + "\n" +
"<HTML>\n" +
"<HEAD>\n" +
"<TITLE>Resume for " + name + "</TITLE>\n" +
makeStyleSheet(headingFont, headingSize,
bodyFont, bodySize,
fgColor, bgColor) + "\n" +
"</HEAD>\n" +
"<BODY>\n" +
"<CENTER>\n"+
"<SPAN CLASS=\"HEADING1\">" + name + "</SPAN><BR>\n" +
"<SPAN CLASS=\"HEADING2\">" + title + "<BR>\n" +
"<A HREF=\"mailto:" + email + "\">" + email +
"</A></SPAN>\n" +
"</CENTER><BR><BR>\n" +
"<SPAN CLASS=\"HEADING3\">Programming Languages" +
"</SPAN>\n" +
makeList(languages) + "<BR><BR>\n" +
"<SPAN CLASS=\"HEADING3\">Skills and Experience" +
"</SPAN><BR><BR>\n" +
skills + "\n" +
"</BODY></HTML>");
}
// Builds a cascading style sheet with information
// on three levels of headings and overall
// foreground and background cover. Also tells
// Internet Explorer to change color of mailto link
// when mouse moves over it.
private String makeStyleSheet(String headingFont,
int heading1Size,
String bodyFont,
int bodySize,
String fgColor,
String bgColor) {
int heading2Size = heading1Size*7/10;
int heading3Size = heading1Size*6/10;
String styleSheet =
"<STYLE TYPE=\"text/css\">\n" +
"<!--\n" +
".HEADING1 { font-size: " + heading1Size + "px;\n" +
" font-weight: bold;\n" +
" font-family: " + headingFont +
"Arial, Helvetica, sans-serif;\n" +
"}\n" +
".HEADING2 { font-size: " + heading2Size + "px;\n" +
" font-weight: bold;\n" +
" font-family: " + headingFont +
"Arial, Helvetica, sans-serif;\n" +
"}\n" +
".HEADING3 { font-size: " + heading3Size + "px;\n" +
" font-weight: bold;\n" +
" font-family: " + headingFont +
"Arial, Helvetica, sans-serif;\n" +
"}\n" +
"BODY { color: " + fgColor + ";\n" +
" background-color: " + bgColor + ";\n" +
" font-size: " + bodySize + "px;\n" +
" font-family: " + bodyFont +
"Times New Roman, Times, serif;\n" +
"}\n" +
"A:hover { color: red; }\n" +
"-->\n" +
"</STYLE>";
return(styleSheet);
}
// Replaces null strings (no such parameter name) or
// empty strings (e.g., if textfield was blank) with
// the replacement. Returns the original string otherwise.
private String replaceIfMissing(String orig,
String replacement) {
if ((orig == null) || (orig.length() == 0)) {
return(replacement);
} else {
return(orig);
}
}
// Replaces null strings, empty strings, or the string
// "default" with the replacement.
// Returns the original string otherwise.
private String replaceIfMissingOrDefault(String orig,
String replacement) {
if ((orig == null) ||
(orig.length() == 0) ||
(orig.equals("default"))) {
return(replacement);
} else {
return(orig + ", ");
}
}
// Takes a string representing an integer and returns it
// as an int. Returns a default if the string is null
// or in an illegal format.
private int getSize(String sizeString, int defaultSize) {
try {
return(Integer.parseInt(sizeString));
} catch(NumberFormatException nfe) {
return(defaultSize);
}
}
// Given "Java,C++,Lisp", "Java C++ Lisp" or
// "Java, C++, Lisp", returns
// "<UL>
// <LI>Java
// <LI>C++
// <LI>Lisp
// </UL>"
private String makeList(String listItems) {
StringTokenizer tokenizer =
new StringTokenizer(listItems, ", ");
String list = "<UL>\n";
while(tokenizer.hasMoreTokens()) {
list = list + " <LI>" + tokenizer.nextToken() + "\n";
}
list = list + "</UL>";
return(list);
}
// Show a confirmation page when they press the
// "Submit" button.
private void showConfirmation(HttpServletRequest request,
PrintWriter out) {
String title = "Submission Confirmed.";
out.println(ServletUtilities.headWithTitle(title) +
"<BODY>\n" +
"<H1>" + title + "</H1>\n" +
"Your resume should appear on-line within\n" +
"24 hours. If it doesn't, try submitting\n" +
"again with a different email address.\n" +
"</BODY></HTML>");
}
// Why it is bad to give your email address to untrusted sites
private void storeResume(HttpServletRequest request) {
String email = request.getParameter("email");
putInSpamList(email);
}
private void putInSpamList(String emailAddress) {
// Code removed to protect the guilty.
}
}
Try entering code for a picture in the skills text area. Filtering HTML.
First version:
package coreservlets;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
/** Servlet that displays a fragment of some Java code,
* but forgets to filter out the HTML-specific characters
* (the less-than sign in this case).
* <P>
* Taken from Core Servlets and JavaServer Pages
* from Prentice Hall and Sun Microsystems Press,
* http://www.coreservlets.com/.
* © 2000 Marty Hall; may be freely used or adapted.
*/
public class BadCodeServlet extends HttpServlet {
private String codeFragment =
"if (a<b) {\n" +
" doThis();\n" +
"} else {\n" +
" doThat();\n" +
"}\n";
public String getCodeFragment() {
return(codeFragment);
}
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "The Java 'if' Statement";
out.println(ServletUtilities.headWithTitle(title) +
"<BODY>\n" +
"<H1>" + title + "</H1>\n" +
"<PRE>\n" +
getCodeFragment() +
"</PRE>\n" +
"Note that you <I>must</I> use curly braces\n" +
"when the 'if' or 'else' clauses contain\n" +
"more than one expression.\n" +
"</BODY></HTML>");
}
}
Try it here
to see why it's called BadCodeServlet. Here's the one that properly filters HTML characters:
I just hope that the stunning beauty of this short code fragment is obvious and refreshing to you.package coreservlets; /** Subclass of BadCodeServlet that keeps the same doGet method * but filters the code fragment for HTML-specific characters. * You should filter strings that are likely to contain * special characters (like program excerpts) or strings * that are derived from user input. ** Taken from Core Servlets and JavaServer Pages * from Prentice Hall and Sun Microsystems Press, * http://www.coreservlets.com/. * © 2000 Marty Hall; may be freely used or adapted. */
public class FilteredCodeServlet extends BadCodeServlet { public String getCodeFragment() { return(ServletUtilities.filter(super.getCodeFragment())); } }
The functionality is the one expected.
4. Handling the Client Request: HTTP Request Headers
Printing all headers:
package coreservlets;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
/** Shows all the request headers sent on this
* particular request.
* <P>
* Taken from Core Servlets and JavaServer Pages
* from Prentice Hall and Sun Microsystems Press,
* http://www.coreservlets.com/.
* © 2000 Marty Hall; may be freely used or adapted.
*/
public class ShowRequestHeaders extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "Servlet Example: Showing Request Headers";
out.println(ServletUtilities.headWithTitle(title) +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H1 ALIGN=CENTER>" + title + "</H1>\n" +
"<B>Request Method: </B>" +
request.getMethod() + "<BR>\n" +
"<B>Request URI: </B>" +
request.getRequestURI() + "<BR>\n" +
"<B>Request Protocol: </B>" +
request.getProtocol() + "<BR><BR>\n" +
"<TABLE BORDER=1 ALIGN=CENTER>\n" +
"<TR BGCOLOR=\"#FFAD00\">\n" +
"<TH>Header Name<TH>Header Value");
Enumeration headerNames = request.getHeaderNames();
while(headerNames.hasMoreElements()) {
String headerName = (String)headerNames.nextElement();
out.println("<TR><TD>" + headerName);
out.println(" <TD>" + request.getHeader(headerName));
}
out.println("</TABLE>\n</BODY></HTML>");
}
/** Let the same servlet handle both GET and POST. */
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
See it running here. Try using it with the text browser that we developed in section 2.
Password protected servlet:
package coreservlets;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.Properties;
import sun.misc.BASE64Decoder;
/** Example of password-protected pages handled directly
* by servlets.
* <P>
* Taken from Core Servlets and JavaServer Pages
* from Prentice Hall and Sun Microsystems Press,
* http://www.coreservlets.com/.
* © 2000 Marty Hall; may be freely used or adapted.
*/
public class ProtectedPage extends HttpServlet {
private Properties passwords;
private String passwordFile;
/** Read the password file from the location specified
* by the passwordFile initialization parameter.
*/
public void init(ServletConfig config)
throws ServletException {
super.init(config);
try {
passwordFile = config.getInitParameter("passwordFile");
passwords = new Properties();
passwords.load(new FileInputStream(passwordFile));
} catch(IOException ioe) {}
}
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String authorization = request.getHeader("Authorization");
if (authorization == null) {
askForPassword(response);
} else {
String userInfo = authorization.substring(6).trim();
BASE64Decoder decoder = new BASE64Decoder();
String nameAndPassword =
new String(decoder.decodeBuffer(userInfo));
int index = nameAndPassword.indexOf(":");
String user = nameAndPassword.substring(0, index);
String password = nameAndPassword.substring(index+1);
String realPassword = passwords.getProperty(user);
if ((realPassword != null) &&
(realPassword.equals(password))) {
String title = "Welcome to the Protected Page";
out.println(ServletUtilities.headWithTitle(title) +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H1 ALIGN=CENTER>" + title + "</H1>\n" +
"Congratulations. You have accessed a\n" +
"highly proprietary company document.\n" +
"Shred or eat all hardcopies before\n" +
"going to bed tonight.\n" +
"</BODY></HTML>");
} else {
askForPassword(response);
}
}
}
// If no Authorization header was supplied in the request.
private void askForPassword(HttpServletResponse response) {
response.setStatus(response.SC_UNAUTHORIZED); // Ie 401
response.setHeader("WWW-Authenticate",
"BASIC realm=\"privileged-few\"");
}
/** Handle GET and POST identically. */
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
Log in from here (note how the servlet
is called). Here's what you need also:
Notice it's up to you how you call, where you put, and what you put in the passwords file.burrowww.cs.indiana.edu% cd $coreServlets burrowww.cs.indiana.edu% ls BadCodeServlet.java PasswordBuilder.class ShowParameters.java FilteredCodeServlet.java PasswordBuilder.java ShowParameters.java~ HelloWWW.class PasswordBuilder.java~ ShowRequestHeaders.java HelloWWW.java ProtectedPage.java SnoopServlet.class HelloWWW2.java ServletTemplate.class SnoopServlet.java HelloWWW3.java ServletTemplate.java SubmitResume.java HelloWorld.class ServletUtilities.java ThreeParams.java HelloWorld.java ShowCGIVariables.java coreservlets LotteryNumbers.java ShowMessage.java burrowww.cs.indiana.edu% cat PasswordBuilder.java import java.util.*; import java.io.*; /** Application that writes a simple Java properties file * containing usernames and associated passwords. ** Taken from Core Servlets and JavaServer Pages * from Prentice Hall and Sun Microsystems Press, * http://www.coreservlets.com/. * © 2000 Marty Hall; may be freely used or adapted. */
public class PasswordBuilder { public static void main(String[] args) throws Exception { Properties passwords = new Properties(); passwords.put("dgerman" , "adrian"); passwords.put("flaradam", "francisco"); passwords.put("sapark" , "sangwook"); passwords.put("asalaev" , "andrey"); passwords.put("rnajlis" , "bob"); // This location should *not* be Web-accessible. String passwordFile = "/u/dgerman/passwords.properties"; FileOutputStream out = new FileOutputStream(passwordFile); // Using JDK 1.1 for portability among all servlet // engines. In JDK 1.2, use "store" instead of "save" // to avoid deprecation warnings. passwords.save(out, "Passwords"); } } burrowww.cs.indiana.edu%
5. Accessing the Standard CGI Variables.
This already appears in the notes of Tuesday.
6. Generating the Server Response: HTTP Status Codes
7. Generating the Server Response: HTTP Response Headers
8. Handling Cookies
9. Session Tracking.
A348/A548