Servlets(Hunter) Chapt 6

Download Report

Transcript Servlets(Hunter) Chapt 6

Chapter 6
Multimedia content
wml file for phone (for a servlet to
find the location for an area code)
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC
"-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<card id="AreaCode" title="Enter an Area Code">
<do type="accept" label="Enter">
<go href="servlet/AreaCode?code=$(code)"/>
</do>
<p>
Enter an Area Code: <input type="text" name="code"/>
</p>
</card>
</wml>
I used an html form
<FORM Method=GET
Action="http://localhost:8080/servlet/AreaCode">
input area code <input type=text
name="code"><p>
<input type =submit>
</form>
It “sends” an xml (wml) doc
• <?xml version="1.0"?>
• <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML
1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
• <wml>
• <card id="Code" title="Code">
• <p>
• Area code '607'<br/>
• is New York.<br/>
• </p>
• </card>
• </wml>
AreaCode
public class AreaCode extends HttpServlet {
Properties lookup = new Properties();
public void init() {
// Transfer raw data from below into a fast-lookup Properties list
for (int i = 0; i < data.length; i++) {
Object[] record = data[i];
String state = (String) record[0];
int[] codes = (int[]) record[1];
for (int j = 0; j < codes.length; j++) {
lookup.put(String.valueOf(codes[j]), state);
}
}
}
AreaCode
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/vnd.wap.wml");
PrintWriter out = res.getWriter();
String msg = null;
String code = req.getParameter("code");
String region = null;
if (code != null) {
region = lookup.getProperty(code); }
out.println("<?xml version=\"1.0\"?>");
out.println("<!DOCTYPE wml PUBLIC " +
"\"-//WAPFORUM//DTD WML 1.1//EN\" " +
"\"http://www.wapforum.org/DTD/wml_1.1.xml\">");
out.println("<wml>");
out.println("<card id=\"Code\" title=\"Code\">");
out.println(" <p>");
out.println(" Area code '" + code + "'<br/>");
if (region != null) {
out.println(" is " + region + ".<br/>"); }
else {
out.println(" is not valid.<br/>"); }
out.println(" </p>");
out.println("</card>");
out.println("</wml>"); }
AreaCode –just part of object[][]array
// Raw area code data for each region
private Object[][] data = new Object[][] {
{ "Toll Free", new int[] { 800, 855, 866, 877, 888 } },
{ "Alabama", new int[] { 205, 256, 334 } },
{ "Alaska", new int[] { 907 } },
{ "Alberta", new int[] { 403, 780 } },
{ "Arizona", new int[] { 480, 520, 602, 623 } },
{ "Arkansas", new int[] { 501, 870 } },
{ "British Columbia", new int[] { 250, 604 } },
{ "California", new int[] { 209, 213, 310, 323, 369, 408, 415, 424, 510,
530, 559, 562, 619, 626, 627, 650, 661, 707, 714, 760, 805, 818, 831,
858, 909, 916, 925, 949 } },
{ "Colorado", new int[] { 303, 719, 720, 970 } },
{ "Connecticut", new int[] { 203, 475, 860, 959 } },
{ "Deleware", new int[] { 302 } },
{ "District of Columbia", new int[] { 202 } },
{ "Florida", new int[] { 305, 321, 352, 407, 561, 727, 786, 813, 850, 863,
904, 941, 954 } },
{ "Georgia", new int[] { 229, 404, 478, 678, 706, 770, 912 } },
{ "Hawaii", new int[] { 808 } },
{ "Idaho", new int[] { 208 } },
{ "Illinois", new int[] { 217, 224, 309, 312, 618, 630, 708, 773, 815,
847 } },
{ "Indiana", new int[] { 219, 317, 765, 812 } },
{ "Iowa", new int[] { 319, 515, 712 } },
{ "Kansas", new int[] { 316, 785, 913 } },
{ "Kentucky", new int[] { 270, 502, 606, 859 } },
//lots more
AreaCode
• Does not work in servletserver, but did
work fine in Tomcat
• Properties class is part of the API
• I also created a similar application in java
which worked fine.
Using graphics in servlets
• For this servlet you’ll need 3 classes from Acme. You
can find them yourself by searching.
• I will put the java files in our class directory
(higgindm/internet programming) They are at
http://employees.oneonta.edu/Higgindm/internet
programming/java/IntHashtable.java
(etc)
• The classes are
– IntHashtable
– ImageEncoder
– GifEncoder
• Pay attention to the directory structure. These will need
to be in special packages
Using graphics in servlets
classes
Acme
JPM
Encoders
GifEncoder
ImageEncoder
IntHashtable
Other sources
• There are other encoders available,
including some from SUN.
• Directories
HelloWorld in Graphics
HelloWorld in Graphics
import java.io.*;
import java.awt.*;
import javax.servlet.*;
import javax.servlet.http.*;
import Acme.JPM.Encoders.GifEncoder;
public class HelloWorldGraphics extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
ServletOutputStream out = res.getOutputStream(); // binary output!
Frame frame = null;
Graphics g = null;
try {
// Create an unshown frame
frame = new Frame();
frame.addNotify();
// Get a graphics region, using the Frame
Image image = frame.createImage(400, 60);
g = image.getGraphics();
// Draw "Hello World!" to the off-screen graphics context
g.setFont(new Font("Serif", Font.ITALIC, 48));
g.drawString("Hello World!", 10, 50);
// Encode the off-screen image into a GIF and send it to the client
res.setContentType("image/gif");
GifEncoder encoder = new GifEncoder(image, out);
encoder.encode(); }
finally {
// Clean up resources
if (g != null) g.dispose();
if (frame != null) frame.removeNotify(); } }}
DeColorize
DeColorize
• This used 3 classes from ACME plus the
GrayscaleFilter from text chapter 6. (as above:
ImageEncoder, GifEncoder, IntHashtable)
• See previous slide for ACME, here’s a link for
GifEncoder:
http://www.acme.com/java/software/Acme.JPM.
Encoders.GifEncoder.html
• If you are compiling in your java\bin directory,
remember, as with text code classes, you’ll need
to drop the package structure into webapps
classes directory of tomcat
A page on the ACME site
DeColorize
import com.oreilly.servlet.ServletUtils;
import Acme.JPM.Encoders.*;
public class DeColorize extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("image/gif");
ServletOutputStream out = res.getOutputStream();
// Get the image location from the path info
URL source = ServletUtils.getResource(getServletContext(),
req.getPathInfo());
if (source == null) {
res.sendError(res.SC_NOT_FOUND,
"Extra path information must point to an image");
return;
}
// Construct an unshown frame
// No addNotify() because its peer isn't needed
Frame frame = new Frame();
DeColorize
// Load the image
Image image = Toolkit.getDefaultToolkit().getImage(source);
MediaTracker mt = new MediaTracker(frame);
mt.addImage(image, 0);
try {
mt.waitForAll();
}
catch (InterruptedException e) {
res.sendError(res.SC_INTERNAL_SERVER_ERROR,
"Interrupted while loading image: " +
ServletUtils.getStackTraceAsString(e));
return;
}
// Get the size of the image
int width = image.getWidth(frame);
int height = image.getHeight(frame);
// Make sure we are reading valid image data
if (width <= 0 || height <= 0) {
res.sendError(res.SC_NOT_FOUND,
"Extra path information must point to a valid image");
return;
}
// Create an image to match, run through a filter
Image filtered = frame.createImage(
new FilteredImageSource(image.getSource(),
new GrayscaleImageFilter()));
// Encode and return the filtered image
GifEncoder encoder = new GifEncoder(filtered, out);
encoder.encode(); }}
Caching images
• Hunter gives tips for caching the
decolorized images in a hashtable.
• If a request comes in for a new image we
go ahead and decolorize, if the image is
already there, we send it to the user.
Cache DeColorize: modify
DeColorize
• Add a Hashtable:
Hashtable gifs=new Hashtable();
• Create a byte array outputstream:
ByteArrayOutputStream baos= new ByteArrayOutputStream(1024);
• After checking for null source, check if already saved this image:
if(gifs.containsKey(source)){
baos=(ByteArrayOutputStream)gifs.get(source);
baos.writeTo(out);
return;}
• Otherwise, encode it to the Hashtable and also write to client
GifEncoder encoder = new GifEncoder(filtered, baos);
encoder.encode();
gifs.put(source,baos);
baos.writeTo(out);
}
Merlin, for example…
Cache decolorizer
• Remember, as with our view resources
examples:
• Unless you write code to do
upcase/lowcase on the pathinfo, java IS
case sensitive and you may not get a
match for a file merlin.gif if the file is
merlin.GIF
Like view resource…but compress
if possible
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.zip.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.oreilly.servlet.ServletUtils;
public class ViewResourceCompress extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
OutputStream out = null;
// Select the appropriate content encoding based on the
// client's Accept-Encoding header. Choose GZIP if the header
// includes "gzip". Choose ZIP if the header includes "compress".
// Choose no compression otherwise. Make sure the Content-Encoding
// uses the "x-" prefix if and only if the Accept-Encoding does.
String encodings = req.getHeader("Accept-Encoding");
if (encodings != null && encodings.indexOf("gzip") != -1) {
// Go with GZIP
if (encodings.indexOf("x-gzip") != -1) {
res.setHeader("Content-Encoding", "x-gzip");
}
else {
res.setHeader("Content-Encoding", "gzip");
}
out = new GZIPOutputStream(res.getOutputStream());
}
Compress resources servlet
else if (encodings != null && encodings.indexOf("compress") != -1) {
// Go with ZIP
if (encodings.indexOf("x-compress") != -1) {
res.setHeader("Content-Encoding", "x-compress");
}
else {
res.setHeader("Content-Encoding", "compress");
}
out = new ZipOutputStream(res.getOutputStream());
((ZipOutputStream)out).putNextEntry(new ZipEntry("dummy name"));
}
else {
// No compression
out = res.getOutputStream();
}
res.setHeader("Vary", "Accept-Encoding");
// Get the resource to view
URL url = null;
try {
url = ServletUtils.getResource(getServletContext(), req.getPathInfo());
}
catch (IOException e) {
res.sendError(
res.SC_NOT_FOUND,
"Extra path info must point to a valid resource to view: " +
e.getMessage());
}
Compress resources servlet
// Connect to the resource
URLConnection con = url.openConnection();
con.connect();
// Get and set the type of the resource
String contentType = con.getContentType();
res.setContentType(contentType);
// Return the resource
try {
ServletUtils.returnURL(url, out);
}
catch (IOException e) {
res.sendError(res.SC_INTERNAL_SERVER_ERROR,
"Problem sending resource: " + e.getMessage());
}
// Write the compression trailer and close the output stream
out.close();
}
}
ServerPush
• Server Push is the server-side version of
the client “request- refresh” servlets we
saw.
• It uses a com/oreilly/class
MultipartResponse to package a series of
web pages to be “pushed” to the client.
• IE does not support server push but it runs
ok in current version (7?) of Netscape.
sending country names and flags
ServletOutputStream out = res.getOutputStream(); // some binary
output
// Prepare a multipart response
MultipartResponse multi = new MultipartResponse(res);
// send a name, then a country's flag
for (int i = 0; i < country.length; i++) {//for
multi.startResponse("text/html");
out.println("<html><title>"+country[i]+"</title></html>");
try { Thread.sleep(1000); } catch (InterruptedException e) { }
multi.endResponse();
multi.startResponse("image/gif");
try {ServletUtils.returnFile(req.getRealPath(flags[i]), out); }
catch (FileNotFoundException e) {throw new
ServletException("Could not find file: " + e.getMessage());}
try { Thread.sleep(1000); } catch (InterruptedException e) { }
images
• Tomcat will find images in your context if
you have an images directory on the same
level as your web-inf directory.
My first “flag” was simpsons