Rearrangement of servlet package. Introduced abstract base servlet

and wrote subclasses for one servlet to one hop application
(ServletClient) and one servlet to multiple hop applications on one server
(MultiServletClient).
This commit is contained in:
hns 2001-03-02 15:45:24 +00:00
parent dd011fe911
commit 874e21b961
4 changed files with 441 additions and 246 deletions

View file

@ -0,0 +1,286 @@
// ServletClient.java
// Copyright (c) Hannes Wallnöfer, Raphael Spannocchi 1998-2000
/* Portierung von helma.asp.AspClient auf Servlets */
/* Author: Raphael Spannocchi Datum: 27.11.1998 */
package helma.servlet;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.util.*;
import helma.framework.*;
import helma.objectmodel.Node;
import helma.util.*;
/**
* This is an abstract Hop servlet adapter. This class communicates with hop applications
* via RMI. Subclasses are either one servlet per app, or one servlet that handles multiple apps
*/
public abstract class AbstractServletClient extends HttpServlet {
String host = null;
int port = 0;
int uploadLimit; // limit to HTTP uploads in kB
String hopUrl;
String cookieDomain;
boolean caching;
boolean debug;
public void init (ServletConfig init) {
host = init.getInitParameter ("host");
if (host == null) host = "localhost";
String portstr = init.getInitParameter ("port");
port = portstr == null ? 5055 : Integer.parseInt (portstr);
String upstr = init.getInitParameter ("uploadLimit");
uploadLimit = upstr == null ? 500 : Integer.parseInt (upstr);
cookieDomain = init.getInitParameter ("cookieDomain");
hopUrl = "//" + host + ":" + port + "/";
debug = ("true".equalsIgnoreCase (init.getInitParameter ("debug")));
caching = ! ("false".equalsIgnoreCase (init.getInitParameter ("caching")));
}
abstract IRemoteApp getApp (String appID) throws Exception;
abstract void invalidateApp (String appID);
abstract String getAppID (String reqpath);
abstract String getRequestPath (String reqpath);
public void doGet (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
execute (request, response);
}
public void doPost (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
execute (request, response);
}
protected void execute (HttpServletRequest request, HttpServletResponse response) {
String protocol = request.getProtocol ();
Cookie[] cookies = request.getCookies();
// get app and path from original request path
String pathInfo = request.getPathInfo ();
String appID = getAppID (pathInfo);
RequestTrans reqtrans = new RequestTrans ();
reqtrans.path = getRequestPath (pathInfo);
try {
if (cookies != null) {
for (int i=0; i < cookies.length;i++) try { // get Cookies
String nextKey = cookies[i].getName ();
String nextPart = cookies[i].getValue ();
if ("HopSession".equals (nextKey))
reqtrans.session = nextPart;
else
reqtrans.set (nextKey, nextPart);
} catch (Exception badCookie) {}
}
// check if we need to create a session id
if (reqtrans.session == null) {
reqtrans.session = Long.toString (Math.round (Math.random ()*Long.MAX_VALUE), 16);
reqtrans.session += "@"+Long.toString (System.currentTimeMillis (), 16);
Cookie c = new Cookie("HopSession", reqtrans.session);
c.setPath ("/");
if (cookieDomain != null)
c.setDomain (cookieDomain);
response.addCookie(c);
}
String host = request.getHeader ("Host");
if (host != null) {
host = host.toLowerCase();
reqtrans.set ("http_host", host);
}
String referer = request.getHeader ("Referer");
if (referer != null)
reqtrans.set ("http_referer", referer);
String remotehost = request.getRemoteAddr ();
if (remotehost != null)
reqtrans.set ("http_remotehost", remotehost);
String browser = request.getHeader ("User-Agent");
if (browser != null)
reqtrans.set ("http_browser", browser);
for (Enumeration e = request.getParameterNames(); e.hasMoreElements(); ) {
// Params parsen
String nextKey = (String)e.nextElement();
String[] paramValues = request.getParameterValues(nextKey);
String nextValue = paramValues[0]; // Only take first value
reqtrans.set (nextKey, nextValue); // generic Header, Parameter
}
String contentType = request.getContentType();
if (contentType != null && contentType.indexOf("multipart/form-data")==0) {
// File Upload
Uploader up;
try {
if ((up = getUpload (uploadLimit, request)) != null) {
Hashtable upload = up.getParts ();
for (Enumeration e = upload.keys(); e.hasMoreElements(); ) {
String nextKey = (String) e.nextElement ();
Object nextPart = upload.get (nextKey);
reqtrans.set (nextKey, nextPart);
}
}
} catch (Exception upx) {
String uploadErr = upx.getMessage ();
if (uploadErr == null || uploadErr.length () == 0)
uploadErr = upx.toString ();
reqtrans.set ("uploadError", uploadErr);
}
}
// get RMI ref to application and execute request
IRemoteApp app = getApp (appID);
ResponseTrans restrans = null;
try {
restrans = app.execute (reqtrans);
} catch (RemoteException cnx) {
invalidateApp (appID);
app = getApp (appID);
app.ping ();
restrans = app.execute (reqtrans);
}
writeResponse (response, restrans, cookies, protocol);
} catch (Exception x) {
invalidateApp (appID);
try {
response.setContentType ("text/html");
Writer out = response.getWriter ();
if (debug)
out.write ("<b>Error:</b><br>" +x);
else
out.write ("This server is temporarily unavailable. Please check back later.");
out.flush ();
} catch (Exception io_e) {}
}
}
private void writeResponse (HttpServletResponse res, ResponseTrans trans, Cookie[] cookies, String protocol) {
for (int i = 0; i < trans.countCookies(); i++) try {
Cookie c = new Cookie(trans.getKeyAt(i), trans.getValueAt(i));
c.setPath ("/");
if (cookieDomain != null)
c.setDomain (cookieDomain);
int expires = trans.getDaysAt(i);
if (expires > 0)
c.setMaxAge(expires * 60*60*24); // Cookie time to live, days -> seconds
res.addCookie(c);
} catch (Exception ign) {}
if (trans.redirect != null) {
try {
res.sendRedirect(trans.redirect);
} catch(Exception io_e) {}
} else {
if (!trans.cache || ! caching) {
// Disable caching of response.
if (protocol == null || !protocol.endsWith ("1.1"))
res.setHeader ("Pragma", "no-cache"); // for HTTP 1.0
else
res.setHeader ("Cache-Control", "no-cache"); // for HTTP 1.1
}
res.setContentLength (trans.getContentLength ());
res.setContentType (trans.contentType);
try {
OutputStream out = res.getOutputStream ();
out.write (trans.getContent ());
out.close ();
} catch(Exception io_e) {}
}
}
private void redirectResponse (HttpServletRequest request, HttpServletResponse res, ResponseTrans trans, String url) {
try {
res.sendRedirect(url);
} catch (Exception e) {
System.err.println ("Exception at redirect: " + e + e.getMessage());
}
}
public Uploader getUpload (HttpServletRequest request) throws Exception {
return getUpload (500, request);
}
public Uploader getUpload (int maxKbytes, HttpServletRequest request) throws Exception {
int contentLength = request.getContentLength ();
BufferedInputStream in = new BufferedInputStream (request.getInputStream ());
Uploader up = null;
try {
if (contentLength > maxKbytes*1024) {
// consume all input to make Apache happy
byte b[] = new byte[1024];
int read = 0;
while (read > -1)
read = in.read (b, 0, 1024);
throw new RuntimeException ("Upload exceeds limit of "+maxKbytes+" kb.");
}
String contentType = request.getContentType ();
up = new Uploader(maxKbytes);
up.load (in, contentType, contentLength);
} finally {
try { in.close (); } catch (Exception ignore) {}
}
return up;
}
public Object getUploadPart(Uploader up, String name) {
return up.getParts().get(name);
}
public String getServletInfo(){
return new String("Hop Servlet Client");
}
}

View file

@ -210,8 +210,8 @@ public class AcmeServletClient extends HttpServlet{
}
public String getServletInfo(){
return new String("Helma ServletClient");
public String getServletInfo (){
return new String("Hop ServletClient");
}

View file

@ -0,0 +1,117 @@
// MultiServletClient.java
// Copyright (c) Hannes Wallnöfer 2001
package helma.servlet;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.util.*;
import helma.framework.IRemoteApp;
/**
* This is the HOP servlet adapter. This class communicates with any
* Hop application on a given Hop server, extracting the application name
* from the request path.
*/
public class MultiServletClient extends AbstractServletClient {
private HashMap apps = null;
public void init (ServletConfig init) {
apps = new HashMap ();
super.init (init);
}
IRemoteApp getApp (String appID) throws Exception {
IRemoteApp retval = (IRemoteApp) apps.get (appID);
if (retval != null) {
return retval;
}
retval = (IRemoteApp) Naming.lookup (hopUrl + appID);
apps.put (appID, retval);
return retval;
}
void invalidateApp (String appID) {
apps.remove (appID);
}
String getAppID (String path) {
if (path == null)
throw new RuntimeException ("Invalid request path: "+path);
char[] val = path.toCharArray ();
int len = val.length;
int st = 0;
// advance to start of path
while ((st < len) && (val[st] <= ' ' || val[st] == '/'))
st++;
// eat characters of first path element
int end = st;
while (end < len && val[end] != '/' && val[end] > 20)
end++;
return new String (val, st, end -st);
}
String getRequestPath (String path) {
if (path == null)
return "";
char[] val = path.toCharArray ();
int len = val.length;
int st = 0;
// advance to start of path
while ((st < len) && (val[st] <= ' ' || val[st] == '/'))
st++;
// eat characters of first path element
while (st < len && val[st] != '/')
st++;
if (st < len && val[st] == '/')
st++;
// eat away noise at end of path
while ((st < len) && (val[len - 1] <= ' ' || val[len - 1] == '/'))
len--;
return ((st > 0) || (len < val.length)) ? new String (val, st, len-st) : path;
}
// for testing
public static void main (String args[]) {
AbstractServletClient client = new MultiServletClient ();
// String path = "///appname/do/it/for/me///";
String path = "appname";
System.out.println (client.getAppID (path));
System.out.println (client.getRequestPath (path));
}
}

View file

@ -17,279 +17,71 @@ import helma.objectmodel.Node;
import helma.util.*;
/**
* This is the HOP servlet adapter. This class communicates with hop applications
* via RMI.
* This is the HOP servlet adapter. This class communicates with just
* one Hop application.
*/
public class ServletClient extends HttpServlet{
public class ServletClient extends AbstractServletClient {
private String host = null;
private int port = 0;
private int uploadLimit; // limit to HTTP uploads in kB
private Hashtable apps;
private IRemoteApp app = null;
private String appName;
private String appUrl;
private String cookieDomain;
private boolean caching;
private boolean debug;
public void init (ServletConfig init) {
apps = new Hashtable();
appName = init.getInitParameter ("application");
if (appName == null) appName = "base";
if (appName == null)
appName = "base";
host = init.getInitParameter ("host");
if (host == null) host = "localhost";
String portstr = init.getInitParameter ("port");
port = portstr == null ? 5055 : Integer.parseInt (portstr);
String upstr = init.getInitParameter ("uploadLimit");
uploadLimit = upstr == null ? 500 : Integer.parseInt (upstr);
cookieDomain = init.getInitParameter ("cookieDomain");
appUrl = "//" + host + ":" + port + "/";
debug = ("true".equalsIgnoreCase (init.getInitParameter ("debug")));
caching = ! ("false".equalsIgnoreCase (init.getInitParameter ("caching")));
super.init (init);
}
IRemoteApp getApp (String appID) throws Exception {
if (app != null)
return app;
private IRemoteApp getApp (String appID) throws Exception {
IRemoteApp retval = (IRemoteApp) apps.get (appID);
if (retval != null) {
return retval;
}
retval = (IRemoteApp) Naming.lookup (appUrl + appID);
apps.put (appID, retval);
return retval;
app = (IRemoteApp) Naming.lookup (hopUrl + appName);
return app;
}
public void doGet (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
execute (appName, request, response);
void invalidateApp (String appID) {
app = null;
}
public void doPost (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
execute (appName, request, response);
String getAppID (String path) {
return appName;
}
// not used anymore
private void get(String appID, HttpServletRequest request, HttpServletResponse response) {
String getRequestPath (String path) {
// get request path
if (path != null)
return trim (path);
else
return "";
}
private void execute (String appID, HttpServletRequest request, HttpServletResponse response) {
String protocol = request.getProtocol ();
Cookie[] cookies = request.getCookies();
try {
RequestTrans reqtrans = new RequestTrans ();
if (cookies != null) {
for (int i=0; i < cookies.length;i++) try { // get Cookies
String nextKey = cookies[i].getName ();
String nextPart = cookies[i].getValue ();
if ("HopSession".equals (nextKey))
reqtrans.session = nextPart;
else
reqtrans.set (nextKey, nextPart);
} catch (Exception badCookie) {}
}
// check if we need to create a session id
if (reqtrans.session == null) {
reqtrans.session = Long.toString (Math.round (Math.random ()*Long.MAX_VALUE), 16);
reqtrans.session += "@"+Long.toString (System.currentTimeMillis (), 16);
Cookie c = new Cookie("HopSession", reqtrans.session);
c.setPath ("/");
if (cookieDomain != null)
c.setDomain (cookieDomain);
response.addCookie(c);
}
// get optional path info
String pathInfo = request.getPathInfo ();
if (pathInfo != null)
reqtrans.path = trim (pathInfo);
else
reqtrans.path = "";
String host = request.getHeader ("Host");
if (host != null) {
host = host.toLowerCase();
reqtrans.set ("http_host", host);
}
String referer = request.getHeader ("Referer");
if (referer != null)
reqtrans.set ("http_referer", referer);
String remotehost = request.getRemoteAddr ();
if (remotehost != null)
reqtrans.set ("http_remotehost", remotehost);
String browser = request.getHeader ("User-Agent");
if (browser != null)
reqtrans.set ("http_browser", browser);
for (Enumeration e = request.getParameterNames(); e.hasMoreElements(); ) {
// Params parsen
String nextKey = (String)e.nextElement();
String[] paramValues = request.getParameterValues(nextKey);
String nextValue = paramValues[0]; // Only take first value
reqtrans.set (nextKey, nextValue); // generic Header, Parameter
}
String contentType = request.getContentType();
if (contentType != null && contentType.indexOf("multipart/form-data")==0) {
// File Upload
Uploader up;
try {
if ((up = getUpload (uploadLimit, request)) != null) {
Hashtable upload = up.getParts ();
for (Enumeration e = upload.keys(); e.hasMoreElements(); ) {
String nextKey = (String) e.nextElement ();
Object nextPart = upload.get (nextKey);
reqtrans.set (nextKey, nextPart);
}
}
} catch (Exception upx) {
String uploadErr = upx.getMessage ();
if (uploadErr == null || uploadErr.length () == 0)
uploadErr = upx.toString ();
reqtrans.set ("uploadError", uploadErr);
}
}
// get RMI ref to application and execute request
IRemoteApp app = getApp (appID);
ResponseTrans restrans = null;
try {
restrans = app.execute (reqtrans);
} catch (RemoteException cnx) {
apps.remove (appID);
app = getApp (appID);
app.ping ();
restrans = app.execute (reqtrans);
}
writeResponse (response, restrans, cookies, protocol);
} catch (Exception x) {
apps.remove (appID);
try {
response.setContentType ("text/html");
Writer out = response.getWriter ();
if (debug)
out.write ("<b>Error:</b><br>" +x);
else
out.write ("This server is temporarily unavailable. Please check back later.");
out.flush ();
} catch (Exception io_e) {}
}
}
private void writeResponse (HttpServletResponse res, ResponseTrans trans, Cookie[] cookies, String protocol) {
for (int i = 0; i < trans.countCookies(); i++) try {
Cookie c = new Cookie(trans.getKeyAt(i), trans.getValueAt(i));
c.setPath ("/");
if (cookieDomain != null)
c.setDomain (cookieDomain);
int expires = trans.getDaysAt(i);
if (expires > 0)
c.setMaxAge(expires * 60*60*24); // Cookie time to live, days -> seconds
res.addCookie(c);
} catch (Exception ign) {}
if (trans.redirect != null) {
try {
res.sendRedirect(trans.redirect);
} catch(Exception io_e) {}
} else {
if (!trans.cache || ! caching) {
// Disable caching of response.
if (protocol == null || !protocol.endsWith ("1.1"))
res.setHeader ("Pragma", "no-cache"); // for HTTP 1.0
else
res.setHeader ("Cache-Control", "no-cache"); // for HTTP 1.1
}
res.setContentLength (trans.getContentLength ());
res.setContentType (trans.contentType);
try {
OutputStream out = res.getOutputStream ();
out.write (trans.getContent ());
out.close ();
} catch(Exception io_e) {}
}
}
private void redirectResponse (HttpServletRequest request, HttpServletResponse res, ResponseTrans trans, String url) {
try {
res.sendRedirect(url);
} catch (Exception e) {
System.err.println ("Exception at redirect: " + e + e.getMessage());
}
}
public Uploader getUpload (HttpServletRequest request) throws Exception {
return getUpload (500, request);
}
public Uploader getUpload (int maxKbytes, HttpServletRequest request) throws Exception {
int contentLength = request.getContentLength ();
BufferedInputStream in = new BufferedInputStream (request.getInputStream ());
Uploader up = null;
try {
if (contentLength > maxKbytes*1024) {
// consume all input to make Apache happy
byte b[] = new byte[1024];
int read = 0;
while (read > -1)
read = in.read (b, 0, 1024);
throw new RuntimeException ("Upload exceeds limit of "+maxKbytes+" kb.");
}
String contentType = request.getContentType ();
up = new Uploader(maxKbytes);
up.load (in, contentType, contentLength);
} finally {
try { in.close (); } catch (Exception ignore) {}
}
return up;
}
public Object getUploadPart(Uploader up, String name) {
return up.getParts().get(name);
}
public String getServletInfo(){
return new String("Helma ServletClient");
}
private String trim (String str) {
if (str == null)
return null;
String trim (String str) {
char[] val = str.toCharArray ();
int len = val.length;
int st = 0;
while ((st < len) && (val[st] <= ' ' || val[st] == '/')) {
while ((st < len) && (val[st] <= ' ' || val[st] == '/'))
st++;
}
while ((st < len) && (val[len - 1] <= ' ' || val[len - 1] == '/')) {
while ((st < len) && (val[len - 1] <= ' ' || val[len - 1] == '/'))
len--;
}
return ((st > 0) || (len < val.length)) ? new String (val, st, len-st) : str;
}
// for testing
public static void main (String args[]) {
AbstractServletClient client = new ServletClient ();
String path = "///appname/do/it/for/me///";
System.out.println (client.getAppID (path));
System.out.println (client.getRequestPath (path));
}
}