|
Design of an HTTP Server that uses Reflection for Servlets
A Simple Network Application in Java |
|
Prof. David Bernstein |
| Computer Science Department |
| bernstdh@jmu.edu |
import java.io.*;
/**
* Constructs servlets appropriate based on
* the file-type in the request.
*
* Note that the Singleton pattern is used to construct
* the factory itself.
*
* @version 0.3
* @author Prof. David Bernstein, James Madison University
*/
public class HttpServletFactory
{
// For the Singleton pattern
private static HttpServletFactory instance = new HttpServletFactory();
// Actual attributes
private File file;
private long lastModified;
private NameValueMap associations;
private static final String FILE_NAME
= "associations.dat";
private static final NameValueMap DEFAULT_ASSOCIATIONS
= NameValueMap.createNameValueMap();
/**
* Default Constructor
*/
private HttpServletFactory()
{
file = new File(FILE_NAME);
lastModified = -1;
associations = NameValueMap.createNameValueMap();
loadAssociations();
}
/**
* Create an HttpServletFactory
*/
public static HttpServletFactory createFactory()
{
return instance;
}
/**
* Construct an HttpServlet
*
* @param req The HTTP request
* @param in The HttpInputStream to read from
* @param out The HttpOutputStream to write to
*/
public HttpServlet createServlet(HttpRequest req,
HttpInputStream in, HttpOutputStream out)
{
Class c;
HttpServlet servlet;
String className, ext, fname;
servlet = null;
loadAssociations();
fname = req.getRequestURI();
ext = FileTyper.getExtension(fname);
className = associations.getValue(ext);
if (className == null)
{
servlet = new DefaultHttpServlet(in, out);
}
else if (className.equals("TemplatedHttpServlet"))
{
servlet = new TemplatedHttpServlet(in, out);
}
return servlet;
}
/**
* Load the associations between file types and
* servlets (if they have changed on disk)
*/
private void loadAssociations()
{
BufferedReader in;
long modified;
modified = file.lastModified();
if (modified > lastModified)
{
try
{
in = new BufferedReader(new FileReader(new File(FILE_NAME)));
associations.clear();
associations.putPairs(in, "\\s");
lastModified = modified;
}
catch (Exception e)
{
associations = DEFAULT_ASSOCIATIONS;
}
}
}
}
getConstructors():
getConstructor():
/**
* Construct an HttpServlet
*
* @param req The HTTP request
* @param in The HttpInputStream to read from
* @param out The HttpOutputStream to write to
*/
public HttpServlet createServlet(HttpRequest req,
HttpInputStream in,
HttpOutputStream out)
{
Class c;
HttpServlet servlet;
String className, ext, fname;
servlet = null;
loadAssociations();
fname = req.getRequestURI();
ext = FileTyper.getExtension(fname);
className = associations.getProperty(ext);
if (className == null)
{
servlet = new DefaultHttpServlet(in, out);
}
else // Use reflection to create an appropriate servlet
{
try
{
Class cl = Class.forName(className);
Constructor co = cl.getConstructor(new Class[]{HttpInputStream.class,
HttpOutputStream.class});
servlet = (HttpServlet)co.newInstance(in, out);
}
catch (Exception e)
{
servlet = new DefaultHttpServlet(in, out);
}
}
return servlet;
}
newInstance()
newInstance() requires onesetStreams() in this case)newInstance() (cont.) /**
* Construct an HttpServlet
*
* @param req The HTTP request
* @param in The HttpInputStream to read from
* @param out The HttpOutputStream to write to
*/
public HttpServlet createServlet(HttpRequest req,
HttpInputStream in,
HttpOutputStream out)
{
Class c;
HttpServlet servlet;
String className, ext, fname;
servlet = null;
loadAssociations();
fname = req.getRequestURI();
ext = FileTyper.getExtension(fname);
className = associations.getProperty(ext);
if (className == null)
{
servlet = new DefaultHttpServlet(in, out);
}
else // Use reflection to create an appropriate servlet
{
try
{
c = Class.forName(className);
servlet = (HttpServlet)c.newInstance();
servlet.setStreams(in, out);
}
catch (Exception e)
{
servlet = new DefaultHttpServlet(in, out);
}
}
return servlet;
}
Class object's getMethod()
method to get a Method objectMethod object's
invoke(Object, Object...)
method (passing it the owning object and the actual
parameters)Class object's getMethod()
method to get a Method objectMethod object's
invoke(null, Object...)
methodimport java.lang.reflect.*;
/**
* An example of static and non-static method invocation using
* reflection.
*
* @author Prof. David Bernstein, James Madison University
* @version 1.0
*/
public class MethodExample
{
/**
* The entry point of the application.
*
* @param args The command-line arguments (which are ignored)
*/
public static void main(String[] args) throws Exception
{
Class s_class;
Integer i, j;
Method s_method;
String s, zip;
s = new String("James Madison University");
s_class = s.getClass();
// Using a non-static method
s_method = s_class.getMethod("indexOf", new Class[]{String.class});
i = (Integer)s_method.invoke(s, "University");
System.out.println(i.intValue());
// Using a static method
s_method = s_class.getMethod("valueOf", new Class[]{Object.class});
zip = (String)s_method.invoke(null, new Integer(22801));
System.out.println(zip);
}
}