Servlets chapt4 Information retrieval. Handling requests To build a successful webapp you probably...

94
Servlets chapt4 Information retrieval
  • date post

    20-Dec-2015
  • Category

    Documents

  • view

    218
  • download

    1

Transcript of Servlets chapt4 Information retrieval. Handling requests To build a successful webapp you probably...

Servlets chapt4

Information retrieval

Handling requests

• To build a successful webapp you probably need to know about– The server that will be running your servlets– And the environment (eg., O.S., hardware,

etc.)– Specifics about the client and the nature of

the requests

Methods providing servlets with information

• These methods improve on the CGI environment variables by allowing stronger type-checking.

• CGI has delays caused by the need to pre-calculate environment variables whether they are used or not.

• A CGI program acts independently of the server, once it is launched. Only standard output is available to the program.

• A servlet may be inside the server, or a connected process and so can make ad hoc requests for information from the server.

Type checking comparison, perl, C and java

• Perl checks a port number with code like

$port =$ENV(‘SERVER_PORT’);

Where $port is untyped. • A CGI program in C uses,

char *port=getenv(“SERVER_PORT”);

The chance of an accidental error is high, for example if the environment variable is misspelled, or a datatype mismatch.

• Java code is

int port =req.getServerPort();

And the compiler can insure no spelling errors and correct datatyping.

Table in text pg 73

• Text table shows how servlet functions map to environment variables.

Partial table

SERVER_NAME req.getServerName()

SERVER_PROTOCOL req.getProtocol()

SERVER_PORT req.getServerPort()

PATH_INFO req.getPathInfo()

REMOTE_HOST req.getRemoteHost()

Init parameters

• Init parameters may be associated with specific servlets by name and are set in web.xml and may be used in init() to set initial values or customize behavior.

• A servlet uses getInitialParameter() method to access its initial parameters:

public String ServletConfig. getInitialParameter(String name)

This method returns the value of the named parameter or null if it doesn’t exist.

Since GenericServlet implements ServletConfig interface, it can call the method directly. Initial parameters could be used to identify details of a database connection for a servlet. (like port, host, db, user, password, proxy)

Init parametersimport java.io.*;import java.util.*;import javax.servlet.*;

public class InitSnoop extends GenericServlet {

// No init() method needed

public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { res.setContentType("text/plain"); PrintWriter out = res.getWriter();

out.println("Init Parameters:"); Enumeration list = getInitParameterNames(); while (list.hasMoreElements()) { String name = (String) list.nextElement(); out.println(name + ": " + getInitParameter(name)); } }}

Servlet tag in web.xml<servlet> <servlet-name>InitSnoop</servlet-name> <description> A simple servlet that looks for its init parameters. </description> <servlet-class> InitSnoop </servlet-class> <init-param> <param-name>initialguy </param-name> <param-value>12345</param-value> </init-param> </servlet>

Screenshot of tomcat/initsnoop

ServerSnoopimport java.io.*;import java.util.*;import javax.servlet.*;public class ServerSnoop extends GenericServlet { public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { res.setContentType("text/plain"); PrintWriter out = res.getWriter(); ServletContext context = getServletContext(); out.println("req.getServerName(): " + req.getServerName()); out.println("req.getServerPort(): " + req.getServerPort()); out.println("context.getServerInfo(): " + context.getServerInfo()); out.println("getServerInfo() name: " + getServerInfoName(context.getServerInfo())); out.println("getServerInfo() version: " + getServerInfoVersion(context.getServerInfo())); out.println("context.getAttributeNames():"); Enumeration list = context.getAttributeNames(); while (list.hasMoreElements()) { String name = (String) list.nextElement(); out.println(" context.getAttribute(\"" + name + "\"): " + context.getAttribute(name)); } }

ServerSnoop slide2private String getServerInfoName(String serverInfo) { int slash = serverInfo.indexOf('/'); if (slash == -1) return serverInfo; else return serverInfo.substring(0, slash); }

private String getServerInfoVersion(String serverInfo) { // Version info is everything between the slash and the space int slash = serverInfo.indexOf('/'); if (slash == -1) return null; int space = serverInfo.indexOf(' ', slash); if (space == -1) space = serverInfo.length(); return serverInfo.substring(slash + 1, space); }}

ServerSnoop servlet on Tomcat

Creating a temp file using servletcontext

• Each servlet context gets its own working (temp) directory which is mapped by the attribute javax.servlet.context.tempdir

//get directory

File dir=(File)getServletContext().getAttribute(“javax.servlet.context.tempdir”);

//create a file

File f=File.createTempFile(“xxx”,”.tmp”,dir);

//get ready to write to it

FileOutputStream fout=new FileOutputStream(f);

Here’s the entire WriteToFile servletimport java.io.*;import javax.servlet.*;import javax.servlet.http.*;public class WriteToFile extends GenericServlet { public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {File dir=(File)getServletContext().getAttribute("javax.servlet.context.tempdir");File f=File.createTempFile("xxx",".tmp",dir);FileOutputStream fout=new FileOutputStream(f);//now write stuff to file

//and don’t forget to close the filefout.close();} public String getServletInfo() { return "A servlet that writes to a file in work/ dir"; }}

Running WriteToFile servlet: note file path

WriteToFile servlet output to client

File Location- note URL

Get a file’s locationimport java.io.*;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;public class FileLocation extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/plain"); PrintWriter out = res.getWriter();

if (req.getPathInfo() != null) { out.println("The file \"" + req.getPathInfo() + "\""); out.println("Is stored at \"" + req.getPathTranslated() + "\""); } else { out.println("Path info is null, no file to lookup"); } }}

http://localhost:8080/myservlets/FileLocation/pathinfo/morepathinfo/Hello.txt

Putting a few tricks together

• An init parameter called key can be used to see if a servlet should be run on a particular server. The key might “fit” the server’s IP and port information for example.

• The KeyedServerLock servlet uses these tricks.

KeyedServerLock – obviously my version is pirated

KeyedServerLockimport java.io.*;import java.net.*;import java.util.*;import javax.servlet.*;

public class KeyedServerLock extends GenericServlet {

// This servlet has no class or instance variables // associated with the locking, so as to simplify // synchronization issues.

public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { res.setContentType("text/plain"); PrintWriter out = res.getWriter();

// The piracy check shouldn't be done in init // because name/port are part of request. String key = getInitParameter("key"); String host = req.getServerName(); int port = req.getServerPort();

KeyedServerLock// Check if the init parameter "key" unlocks this server. if (! keyFitsServer(key, host, port)) { // Explain, condemn, threaten, etc. out.println("Pirated!"); } else { // Give 'em the goods out.println("Valid"); // etc... } } // This method contains the algorithm used to match a key with // a server host and port. This example implementation is extremely // weak and should not be used by commercial sites. // private boolean keyFitsServer(String key, String host, int port) {

if (key == null) return false;

long numericKey = 0; try { numericKey = Long.parseLong(key); } catch (NumberFormatException e) { return false; }

KeyedServerLock// The key must be a 64-bit number equal to the logical not (~) // of the 32-bit IP address concatenated with the 32-bit port number. byte hostIP[]; try { hostIP = InetAddress.getByName(host).getAddress(); } catch (UnknownHostException e) { return false; } // Get the 32-bit IP address long servercode = 0; for (int i = 0; i < 4; i++) { servercode <<= 8; servercode |= hostIP[i]; } // Concatentate the 32-bit port number servercode <<= 32; servercode |= port; // Logical not long accesscode = ~numericKey; // The moment of truth: Does the key match? return (servercode == accesscode); }}

KeyedServerUnlock is the companion for KeyedServerLock –get the key

Init param holds key… I got the key from the keyedserverunlock servlet

<servlet> <servlet-name> KeyedServerLock </servlet-name> <servlet-class> KeyedServerLock </servlet-class> <init-param> <param-name>key </param-name> <param-value> 9151314447111823249 </param-value> <description> The key value to unlock the servlet's functionality </description> </init-param> </servlet>

Using serverlock and serverunlock together: Not sure why keys are off by one!!!

Valid…subtracted one before compare

• Code from serverlock long servercode = 0; for (int i = 0; i < 4; i++) { servercode <<= 8; servercode |= hostIP[i]; } // Concatentate the 32-bit port number servercode <<= 32; servercode |= port;• Code from serverunlocklong servercode = 0; for (int i = 0; i < 4; i++) { servercode <<= 8; servercode |= hostIP[i]; } // Concatentate the 32-bit port number servercode <<= 32; servercode |= port; // The key is the logical not return ~servercode;

Getting info about the client machine

• ServletRequest methods getRemoteAddr() and getRemoteHost() both return strings and can be used to get some info about the client machine.

• The client IP or remote host name can further be converted into a java InetAddress using its method getByName()

• The next example considers whether we should allow access to restricted material based on the country from which the request comes.

Getting client information: is this client allowed to download?

public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); PrintWriter out = res.getWriter(); // ...Some introductory HTML...then Get the client's hostname String remoteHost = req.getRemoteHost(); // See if the client is allowed if (! isHostAllowed(remoteHost)) { out.println("Access <BLINK>denied</BLINK>"); } else { out.println("Access granted"); // Display download links, etc... } } // Disallow hosts ending with .cu, .ir, .iq, .kp, .ly, .sy, and .sd. private boolean isHostAllowed(String host) { return (!host.endsWith(".cu") && !host.endsWith(".ir") && !host.endsWith(".iq") && !host.endsWith(".kp") && !host.endsWith(".ly") && !host.endsWith(".sy") && !host.endsWith(".sd")); }

Getting client information

Personalized Welcome servlet

• Uses req.getRemoteUser() with a hashtable to keep track of multiple visits in order to greet a user by name.

• (I think) in order to send a greeting other than “welcome” this needs to be combined with the server requiring a name/pw to access the resource

Personalized Welcome servlet (doGet()) String remoteUser = req.getRemoteUser(); if (remoteUser == null) { out.println("Welcome!"); } else { out.println("Welcome, " + remoteUser + "!"); Date lastAccess = (Date) accesses.get(remoteUser); if (lastAccess == null) { out.println("This is your first visit!"); } else { out.println("Your last visit was " +

accesses.get(remoteUser)); } if (remoteUser.equals("PROFESSOR FALKEN")) { out.println("Shall we play a game?"); } accesses.put(remoteUser, new Date()); }

Getting user information

Getting parameters

Getting parameters

• <FORM Method=GET Action="http://localhost:8080/servlet/ParameterSnoop">

• a parameter <input type=text name="word">• another parameter <input type=text

name="value">• an another <input type=text name="thing">• <input type =submit>• </form>

Parameters, continued

ParameterSnoop.java public void doGet(HttpServletRequest req,

HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/plain"); PrintWriter out = res.getWriter(); out.println("Query String:"); out.println(req.getQueryString()); out.println(); out.println("Request Parameters:"); Enumeration enum = req.getParameterNames(); while (enum.hasMoreElements()) { String name = (String) enum.nextElement(); String values[] = req.getParameterValues(name); if (values != null) { for (int i = 0; i < values.length; i++) { out.println(name + " (" + i + "): " + values[i]); } } } }

More values of same parameters

With more values of parameters

The Form revised

<FORM Method=GET Action="http://localhost:8080/servlet/ParameterSnoop">

a parameter <input type=text name="word"><p>same parameter <input type=text name="word"><p>same again <input type=text name="word"><p>another parameter <input type=text name="value"><p>and same parameter <input type=text name="value">a final <input type=text name="thing"><input type =submit></form>

What happens to ‘&’ if entered as a parameter?

Seems to know what to do with them

Uploading a file

form

• <FORM Method=Post• ACTION="http://csci345.oneonta.edu:8080/

myexamples/UploadTest"• ENCTYPE="multipart/form-data">• Name? <input type=text name=submitter><br>• what file? <input type=file name=file><br>• <input type=submit>• </form>

form in IE after browse and select

UploadTest.java public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); PrintWriter out = res.getWriter(); try { // Blindly take it on faith this is a multipart/form-data request

// Construct a MultipartRequest to help read the information. // Pass in the request, a directory to save files to, and the // maximum POST size we should attempt to handle. // Here we (rudely) write to the server root and impose 5 Meg limit. MultipartRequest multi = new MultipartRequest(req, ".", 5 * 1024 * 1024); out.println("<HTML>"); out.println("<HEAD><TITLE>UploadTest</TITLE></HEAD>"); out.println("<BODY>"); out.println("<H1>UploadTest</H1>"); // Print the parameters we received out.println("<H3>Params:</H3>"); out.println("<PRE>"); Enumeration params = multi.getParameterNames(); while (params.hasMoreElements()) { String name = (String)params.nextElement(); String value = multi.getParameter(name); out.println(name + " = " + value); } out.println("</PRE>");

UploadTest.java// Show which files we received out.println("<H3>Files:</H3>"); out.println("<PRE>"); Enumeration files = multi.getFileNames(); while (files.hasMoreElements()) { String name = (String)files.nextElement(); String filename = multi.getFilesystemName(name); String type = multi.getContentType(name); File f = multi.getFile(name); out.println("name: " + name); out.println("filename: " + filename); out.println("type: " + type); if (f != null) { out.println("length: " + f.length()); } out.println(); } out.println("</PRE>"); } catch (Exception e) { out.println("<PRE>"); e.printStackTrace(out); out.println("</PRE>"); } out.println("</BODY></HTML>"); }

Now what?

• On Tomcat files are copied to bin directory and you’ll need to go delete them if you don’t want them.

• You could put a db entry for this file including size, name, etc and provide for user download.

The next dozen slides

• I repeated Hunter’s work but used Jakarta classes.

Jakarta links

• http://commons.apache.org/fileupload/• http://commons.apache.org/fileupload/using.html

• Each file item has a number of properties that might be of interest for your application. For example, every item has a name and a content type, and can provide an InputStream to access its data. On the other hand, you may need to process items differently, depending upon whether the item is a regular form field - that is, the data came from an ordinary text box or similar HTML field - or an uploaded file. The FileItem interface provides the methods to make such a determination, and to access the data in the most appropriate manner.

• Before you can work with the uploaded items, of course, you need to parse the request itself. Ensuring that the request is actually a file upload request is straightforward. FileUpload providesa static method to do this.

// Check that we have a file upload request boolean isMultipart = ServletFileUpload.isMultipartContent(request);

The simplest usage scenario• Uploaded items should be retained in memory as long as they are

reasonably small. • Larger items should be written to a temporary file on disk. • Very large upload requests should not be permitted. • The built-in defaults for the maximum size of an item to be retained

in memory, the maximum permitted size of an upload request, and the location of temporary files are acceptable.

• Handling a request in this scenario couldn't be much simpler: // Create a factory for disk-based file items FileItemFactory factory = new DiskFileItemFactory(); // Create a new file upload handler ServletFileUpload upload = new ServletFileUpload(factory); // Parse the request List /* FileItem */ items = upload.parseRequest(request);

more control• If your usage scenario is close to the simplest case, described

above, but you need a little more control, you can easily customize the behavior of the upload handler or the file item factory or both. The following example shows several configuration options:

// Create a factory for disk-based file items DiskFileItemFactory factory = new DiskFileItemFactory(); // Set factory constraints

factory.setSizeThreshold(yourMaxMemorySize); factory.setRepository(yourTempDirectory);

// Create a new file upload handler ServletFileUpload upload = new ServletFileUpload(factory); // Set overall request size constraint

upload.setSizeMax(yourMaxRequestSize); // Parse the request List /* FileItem */ items = upload.parseRequest(request);

To configure the factory all at once

• Of course, each of the configuration methods is independent of the others, but if you want to configure the factory all at once, you can do that with an alternative constructor, like this:

// Create a factory for disk-based file items DiskFileItemFactory factory = new DiskFileItemFactory( yourMaxMemorySize, yourTempDirectory);

Processing the uploaded items

• Once the parse has completed, you will have a List of file items that you need to process. In most cases, you will want to handle file uploads differently from regular form fields, so you might process the list like this:

// Process the uploaded items Iterator iter = items.iterator(); while (iter.hasNext()) { FileItem item = (FileItem) iter.next(); if (item.isFormField())

{ processFormField(item); } else { processUploadedFile(item); } } For a regular form field, you will most likely be interested only in the

name of the item, and its String value. As you might expect, accessing these is very simple.

// Process a regular form field if (item.isFormField()) { String name = item.getFieldName(); String

value = item.getString(); ... }

For a file upload

• For a file upload, there are several different things you might want to know before you process the content. Here is an example of some of the methods you might be interested in.

// Process a file upload if (!item.isFormField()) { String fieldName = item.getFieldName(); String fileName = item.getName(); String contentType = item.getContentType(); boolean isInMemory = item.isInMemory(); long sizeInBytes = item.getSize(); ... }

process the content as a stream• With uploaded files, you generally will not want to access them via memory,

unless they are small, or unless you have no other alternative. Rather, you will want to process the content as a stream, or write the entire file to its ultimate location. FileUpload provides simple means of accomplishing both of these.

// Process a file upload if (writeToFile) { File uploadedFile = new File(...); item.write(uploadedFile); } else { InputStream uploadedStream = item.getInputStream(); ...

uploadedStream.close(); } • Note that, in the default implementation of FileUpload, write() will attempt to

rename the file to the specified destination, if the data is already in a temporary file. Actually copying the data is only done if the the rename fails, for some reason, or if the data was in memory.

• If you do need to access the uploaded data in memory, you need simply call the get() method to obtain the data as an array of bytes.

• // Process a file upload in memory byte[] data = item.get(); ...

Streaming api: Parsing the request

• First of all, do not forget to ensure, that a request actually is a a file upload request. This is typically done using the same static method, which you already know from the traditional API.

• // Check that we have a file upload request boolean isMultipart =

ServletFileUpload.isMultipartContent(request); • Now we are ready to parse the request into its

constituent items. Here's how we do it: // Create a new file upload handler ServletFileUpload upload = new ServletFileUpload();

Parse the request

// Parse the request FileItemIterator iter = upload.getItemIterator(request); while (iter.hasNext()) { FileItemStream item = iter.next(); String name = item.getFieldName(); InputStream stream = item.openStream(); if (item.isFormField()) { System.out.println("Form field " +

name + " with value " + Streams.asString(stream) + " detected."); }

else { System.out.println("File field " + name + " with file name " + item.getName() + " detected.");

// Process the input stream ... } }

Additional notes

• Many details were omitted from jakarta commons info… like the need for Jakarta-commons-io jar file.

• Try..catch clauses are needed.

• Note imports.

• Only minimal upload service provided.

Success!

And the file really is there…

The servlet… note importsimport java.io.*;import javax.servlet.*;import javax.servlet.http.*;import java.util.*;import org.apache.commons.fileupload.*;

import org.apache.commons.fileupload.disk.*;

import org.apache.commons.fileupload.servlet.*;import org.apache.commons.fileupload.util.*;public class FileUpload extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); PrintWriter out = res.getWriter(); out.println(“servlet upload only supports http post operation”<br>”); out.println("<HTML><BODY>");

out.println("</BODY></HTML>"); }//doGet

Postpublic void doPost(HttpServletRequest request, HttpServletResponse res)

throws ServletException, IOException { res.setContentType("text/html");

String result=""; PrintWriter out = res.getWriter(); // Get the current session object, create one if necessary out.println("<HTML><BODY>"); // Create a factory for disk-based file items // Create a factory for disk-based file items DiskFileItemFactory factory = new DiskFileItemFactory(); // Set factory constraints factory.setSizeThreshold(yourMaxMemorySize); factory.setRepository(yourTempDirectory); // Create a new file upload handler ServletFileUpload upload = new ServletFileUpload(factory); // Set overall request size constraint upload.setSizeMax(yourMaxRequestSize); // Parse the request try{ List /* FileItem */ items = upload.parseRequest(request); // Process the uploaded items

Iterator iter = items.iterator(); while (iter.hasNext()) { FileItem item = (FileItem) iter.next(); if (item.isFormField()) { result= processFormField(item); } else { result =processUploadedFile(item); } }

}//try catch(Exception e){out.println("upload error"+e.toString());}out.println(result);

}

utility functionspublic String processFormField(FileItem item){// Process a form field if (item.isFormField()) { String name = item.getFieldName(); String value = item.getString(); return "name:"+name+"value:"+value;}else return "";}public String processUploadedFile(FileItem item){// Process a file uploadboolean writeToFile=true;File dir=(File)getServletContext().getAttribute("javax.servlet.context.tempdir");//create a file//File uploadedFile=File.createTempFile("upload",".tmp",dir);

if (writeToFile){

try{File uploadedFile=File.createTempFile("upload",".tmp",dir);item.write(uploadedFile);return "successfully written to"+dir+ "upload.tmp";}

catch(Exception e){ return e.toString();}

}////else { InputStream uploadedStream = item.getInputStream(); ... uploadedStream.close(); }return "did not write";}}

Need to do…

• Multipart

• Stream

• Upload to db--- no documentation available at Jakarta Commons for this.

Tomcat servlet examplesRequestHeaderExample

RequestHeaderExample

import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; public class RequestHeaderExample extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setContentType("text/html");

PrintWriter out = response.getWriter(); Enumeration e = request.getHeaderNames(); while (e.hasMoreElements()) { String name = (String)e.nextElement(); String value = request.getHeader(name); out.println(name + " = " + value); } } }

RequestInfoExample

RequestInfoExamplepublic void doGet(HttpServletRequest request, HttpServletResponse

response) throws IOException, ServletException { response.setContentType("text/html"); PrintWriter out = response.getWriter();out.println("<html>"); out.println("<body>"); out.println("<head>"); out.println("<title>Request Information Example</title>");

out.println("</head>"); out.println("<body>"); out.println("<h3>Request Information Example</h3>"); out.println("Method: " + request.getMethod()); out.println("Request URI: " + request.getRequestURI()); out.println("Protocol: " + request.getProtocol());

out.println("PathInfo: " + request.getPathInfo()); out.println("Remote Address: " + request.getRemoteAddr());

out.println("</body>"); out.println("</html>"); }

ViewFile

• I had some problems with this example despite the demos in the text and Tomcat.

• By changing the servlet mapping to /which makes ViewFile the default servlet for the context I

did get getPath() etc to work.• I looked in tomcat’s examples and saw that the url

mapping had to be: /ViewFile/* which allows pathInfo to be entered after the name of a servlet.

• The next couple of slides just use / for the mapping which means pathInfo is not available and you need to use other tricks to find the filename.

http://csci345.oneonta.edu:8080/myexamples/xxx.txt

http://csci345.oneonta.edu:8080/myexamples/.../xxx.txt

Viewing path information, continued public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { // Use a ServletOutputStream because we may pass binary information ServletOutputStream out = res.getOutputStream();res.setContentType("text/html"); // Get the file to view String name=getServletName(); out.println("servlet name"+name+"<br>");

String path=req.getServletPath(); out.println("servlet path"+path+"<br>"); String file1 = req.getPathInfo();

out.println("req.getPathInfo()"+file1+"<br>"); String s4=req.getPathTranslated(); out.println("pathtranslated is"+s4+"<br>");//file=file.substring(1); // No file, nothing to view if (file1 == null) { out.println("No file to view"); return; }

ShowFile servlet

ShowFile servlet

Servlet code public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { // Use a ServletOutputStream because we may pass binary information ServletOutputStream out = res.getOutputStream();//servlet name String name=getServletName(); //possibly other path info String path=req.getServletPath();

String file=path.substring(1); if(file.length()>name.length()){

String tmp=file.substring(0,name.length()); if(tmp.equals(name)&&file.charAt(name.length())=='/') file=file.substring(name.length()+1); }

if (file == null) { out.println("No file to view"); return; } // Get and set the type of the file String contentType = getServletContext().getMimeType(file); res.setContentType(contentType); // Return the file try { ServletUtils.returnFile(file, out); } catch (FileNotFoundException e) { out.println("File not found"); } catch (IOException e) { out.println("Problem sending file: " + e.getMessage()); } }

ShowFile servlet

• File needs to be in tomcat/bin

ViewFile working fine

ViewFileimport java.io.*;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;import com.oreilly.servlet.ServletUtils;public class ViewFile extends HttpServlet { public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { // Use a ServletOutputStream because we may pass binary information ServletOutputStream out = res.getOutputStream(); // Get the file to view String file = req.getPathTranslated(); // No file, nothing to view if (file == null) { out.println("No file to view"); return; } // Get and set the type of the file String contentType = getServletContext().getMimeType(file); res.setContentType(contentType); // Return the file try { ServletUtils.returnFile(file, out); } catch (FileNotFoundException e) { out.println("File not found"); } catch (IOException e) { out.println("Problem sending file: " + e.getMessage()); } }}

ViewFile mapping: file located in root of webapp

<servlet-mapping>

<servlet-name>ViewFile</servlet-name>

<url-pattern>/ViewFile/*</url-pattern>

</servlet-mapping>

UnsafeViewResource provides no protection of server resources

ViewResource

• Uses code in com.oreilly file getResource to check that the file is not coming from a path to WEB-INF or META-INF

ViewResource- error trying to get web.xml

Just a note…unlike browser, java filenames are case sensitive unless otherwise coded

Hardcoding the content-type

• Hardcoding the content-type to application-octet-stream should give a pop up in browser—where to save the file- except in ie

• Makes this a generic file server servlet

Ie ignores contenttype and just displays it

In Netscape, for example

ViewResource: viewing xml

And viewing a gif:

ViewResourcepublic void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { // Use a ServletOutputStream because we may pass binary information ServletOutputStream out = res.getOutputStream(); res.setContentType("text/plain"); // sanity default // 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()); return; } // 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()); } }