Reworked much of the helma servlet code.

Parameter parsing is now done by the servlet itself since we know
best about the encoding used by an application.
AcmeServletClient is gone, the new EmbeddedServletClient
is a subclass of AbstractServletClient, so no more duplicate code here.
This commit is contained in:
hns 2002-05-23 19:31:40 +00:00
parent 14a6f0840e
commit 202575d801
8 changed files with 293 additions and 368 deletions

View file

@ -108,11 +108,11 @@ public class ApplicationManager {
if (server.websrv == null) { if (server.websrv == null) {
Naming.rebind ("//:"+port+"/"+appName, app); Naming.rebind ("//:"+port+"/"+appName, app);
} else { } else {
AcmeServletClient servlet = new AcmeServletClient (app); boolean isRoot = "base".equalsIgnoreCase (appName);
if ("base".equalsIgnoreCase (appName)) EmbeddedServletClient servlet = new EmbeddedServletClient (appName, isRoot);
if (isRoot)
server.websrv.setDefaultServlet (servlet); server.websrv.setDefaultServlet (servlet);
else { else {
// server.websrv.addServlet ("/"+appName+"/", servlet);
server.websrv.addServlet ("/"+appName+"/*", servlet); server.websrv.addServlet ("/"+appName+"/*", servlet);
} }
} }
@ -147,14 +147,17 @@ public class ApplicationManager {
} }
/** /**
* Get an enumeration of all currently running applications. * Get an array containing all currently running applications.
*/ */
public Object[] getApplications () { public Object[] getApplications () {
return applications.values ().toArray (); return applications.values ().toArray ();
} }
public Application getApplication(String name) { /**
return (Application)applications.get(name); * Get an application by name.
} */
public Application getApplication(String name) {
return (Application)applications.get(name);
}
} }

View file

@ -21,13 +21,22 @@ import helma.util.*;
*/ */
public abstract class AbstractServletClient extends HttpServlet { public abstract class AbstractServletClient extends HttpServlet {
// host on which Helma app is running
String host = null; String host = null;
// port of Helma RMI server
int port = 0; int port = 0;
int uploadLimit; // limit to HTTP uploads in kB // limit to HTTP uploads in kB
int uploadLimit;
// RMI url of Helma app
String hopUrl; String hopUrl;
// cookie domain to use
String cookieDomain; String cookieDomain;
// default encoding for requests
String defaultEncoding;
// allow caching of responses
boolean caching; boolean caching;
// enable debug output
boolean debug; boolean debug;
static final byte HTTP_GET = 0; static final byte HTTP_GET = 0;
@ -35,7 +44,7 @@ public abstract class AbstractServletClient extends HttpServlet {
public void init (ServletConfig init) throws ServletException { public void init (ServletConfig init) throws ServletException {
super.init (init); super.init (init);
host = init.getInitParameter ("host"); host = init.getInitParameter ("host");
if (host == null) host = "localhost"; if (host == null) host = "localhost";
@ -49,6 +58,8 @@ public abstract class AbstractServletClient extends HttpServlet {
hopUrl = "//" + host + ":" + port + "/"; hopUrl = "//" + host + ":" + port + "/";
defaultEncoding = init.getInitParameter ("charset");
debug = ("true".equalsIgnoreCase (init.getInitParameter ("debug"))); debug = ("true".equalsIgnoreCase (init.getInitParameter ("debug")));
caching = ! ("false".equalsIgnoreCase (init.getInitParameter ("caching"))); caching = ! ("false".equalsIgnoreCase (init.getInitParameter ("caching")));
@ -88,13 +99,15 @@ public abstract class AbstractServletClient extends HttpServlet {
try { try {
// read and set http parameters // read and set http parameters
for (Enumeration e = request.getParameterNames(); e.hasMoreElements(); ) { Map parameters = parseParameters (request);
String nextKey = (String)e.nextElement(); for (Iterator i=parameters.entrySet().iterator(); i.hasNext(); ) {
String[] paramValues = request.getParameterValues(nextKey); Map.Entry entry = (Map.Entry) i.next ();
if (paramValues != null) { String key = (String) entry.getKey ();
reqtrans.set (nextKey, paramValues[0]); // set to single string value String[] values = (String[]) entry.getValue ();
if (paramValues.length > 1) if (values != null && values.length > 0) {
reqtrans.set (nextKey+"_array", paramValues); // set string array reqtrans.set (key, values[0]); // set to single string value
if (values.length > 1)
reqtrans.set (key+"_array", values); // set string array
} }
} }
@ -102,13 +115,13 @@ public abstract class AbstractServletClient extends HttpServlet {
String contentType = request.getContentType(); String contentType = request.getContentType();
if (contentType != null && contentType.indexOf("multipart/form-data")==0) { if (contentType != null && contentType.indexOf("multipart/form-data")==0) {
// File Upload // File Upload
Uploader up;
try { try {
if ((up = getUpload (request)) != null) { FileUpload upload = getUpload (request);
Hashtable upload = up.getParts (); if (upload != null) {
for (Enumeration e = upload.keys(); e.hasMoreElements(); ) { Hashtable parts = upload.getParts ();
for (Enumeration e = parts.keys(); e.hasMoreElements(); ) {
String nextKey = (String) e.nextElement (); String nextKey = (String) e.nextElement ();
Object nextPart = upload.get (nextKey); Object nextPart = parts.get (nextKey);
reqtrans.set (nextKey, nextPart); reqtrans.set (nextKey, nextPart);
} }
} }
@ -226,6 +239,13 @@ public abstract class AbstractServletClient extends HttpServlet {
res.setHeader( "WWW-Authenticate", "Basic realm=\"" + trans.realm + "\"" ); res.setHeader( "WWW-Authenticate", "Basic realm=\"" + trans.realm + "\"" );
if (trans.status > 0) if (trans.status > 0)
res.setStatus (trans.status); res.setStatus (trans.status);
// if we don't know which charset to use for parsing HTTP params,
// take the one from the response. This usually works because
// browsers send parrameters in the same encoding as the page
// containing the form has. Problem is we can do this only per servlet,
// not per session or even per page, which would produce too much overhead
if (defaultEncoding == null)
defaultEncoding = trans.charset;
res.setContentLength (trans.getContentLength ()); res.setContentLength (trans.getContentLength ());
res.setContentType (trans.getContentType ()); res.setContentType (trans.getContentType ());
try { try {
@ -245,10 +265,10 @@ public abstract class AbstractServletClient extends HttpServlet {
} }
public Uploader getUpload (HttpServletRequest request) throws Exception { public FileUpload getUpload (HttpServletRequest request) throws Exception {
int contentLength = request.getContentLength (); int contentLength = request.getContentLength ();
BufferedInputStream in = new BufferedInputStream (request.getInputStream ()); BufferedInputStream in = new BufferedInputStream (request.getInputStream ());
Uploader up = null; FileUpload upload = null;
try { try {
if (contentLength > uploadLimit*1024) { if (contentLength > uploadLimit*1024) {
// consume all input to make Apache happy // consume all input to make Apache happy
@ -259,42 +279,165 @@ public abstract class AbstractServletClient extends HttpServlet {
throw new RuntimeException ("Upload exceeds limit of "+uploadLimit+" kb."); throw new RuntimeException ("Upload exceeds limit of "+uploadLimit+" kb.");
} }
String contentType = request.getContentType (); String contentType = request.getContentType ();
up = new Uploader(uploadLimit); upload = new FileUpload(uploadLimit);
up.load (in, contentType, contentLength); upload.load (in, contentType, contentLength);
} finally { } finally {
try { in.close (); } catch (Exception ignore) {} try {
in.close ();
} catch (Exception ignore) {}
} }
return up; return upload;
} }
public Object getUploadPart(Uploader up, String name) { public Object getUploadPart(FileUpload upload, String name) {
return up.getParts().get(name); return upload.getParts().get(name);
} }
/**
* Put name value pair in map.
*
* @param b the character value byte
*
* Put name and value pair in map. When name already exist, add value
* to array of values.
*/
private static void putMapEntry( Map map, String name, String value) {
String[] newValues = null;
String[] oldValues = (String[]) map.get(name);
if (oldValues == null) {
newValues = new String[1];
newValues[0] = value;
} else {
newValues = new String[oldValues.length + 1];
System.arraycopy(oldValues, 0, newValues, 0, oldValues.length);
newValues[oldValues.length] = value;
}
map.put(name, newValues);
}
protected Map parseParameters (HttpServletRequest request) {
String encoding = request.getCharacterEncoding ();
if (encoding == null)
// no encoding from request, use standard one
encoding = defaultEncoding;
if (encoding == null)
encoding = "ISO-8859-1";
HashMap parameters = new HashMap ();
// Parse any query string parameters from the request
try {
parseParameters (parameters, request.getQueryString().getBytes(), encoding);
} catch (Exception e) {
}
// Parse any posted parameters in the input stream
if ("POST".equals(request.getMethod()) &&
"application/x-www-form-urlencoded".equals(request.getContentType())) {
try {
int max = request.getContentLength();
int len = 0;
byte buf[] = new byte[max];
ServletInputStream is = request.getInputStream();
while (len < max) {
int next = is.read(buf, len, max - len);
if (next < 0 ) {
break;
}
len += next;
}
// is.close();
parseParameters(parameters, buf, encoding);
} catch (IllegalArgumentException e) {
} catch (IOException e) {
}
}
return parameters;
}
/**
* Append request parameters from the specified String to the specified
* Map. It is presumed that the specified Map is not accessed from any
* other thread, so no synchronization is performed.
* <p>
* <strong>IMPLEMENTATION NOTE</strong>: URL decoding is performed
* individually on the parsed name and value elements, rather than on
* the entire query string ahead of time, to properly deal with the case
* where the name or value includes an encoded "=" or "&" character
* that would otherwise be interpreted as a delimiter.
*
* NOTE: byte array data is modified by this method. Caller beware.
*
* @param map Map that accumulates the resulting parameters
* @param data Input string containing request parameters
* @param encoding Encoding to use for converting hex
*
* @exception UnsupportedEncodingException if the data is malformed
*/
public static void parseParameters (Map map, byte[] data, String encoding)
throws UnsupportedEncodingException {
if (data != null && data.length > 0) {
int pos = 0;
int ix = 0;
int ox = 0;
String key = null;
String value = null;
while (ix < data.length) {
byte c = data[ix++];
switch ((char) c) {
case '&':
value = new String(data, 0, ox, encoding);
if (key != null) {
putMapEntry(map, key, value);
key = null;
}
ox = 0;
break;
case '=':
key = new String(data, 0, ox, encoding);
ox = 0;
break;
case '+':
data[ox++] = (byte)' ';
break;
case '%':
data[ox++] = (byte)((convertHexDigit(data[ix++]) << 4)
+ convertHexDigit(data[ix++]));
break;
default:
data[ox++] = c;
}
}
//The last value does not end in '&'. So save it now.
if (key != null) {
value = new String(data, 0, ox, encoding);
putMapEntry(map, key, value);
}
}
}
/**
* Convert a byte character value to hexidecimal digit value.
*
* @param b the character value byte
*/
private static byte convertHexDigit( byte b ) {
if ((b >= '0') && (b <= '9')) return (byte)(b - '0');
if ((b >= 'a') && (b <= 'f')) return (byte)(b - 'a' + 10);
if ((b >= 'A') && (b <= 'F')) return (byte)(b - 'A' + 10);
return 0;
}
public String getServletInfo(){ public String getServletInfo(){
return new String("Hop Servlet Client"); return new String("Helma Servlet Client");
} }
} }

View file

@ -1,271 +0,0 @@
// AcmeServletClient.java
// Copyright (c) Hannes Wallnoefer, 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.util.*;
import helma.framework.*;
import helma.framework.core.Application;
import helma.util.Uploader;
/**
* This is the Hop servlet adapter that uses the Acme servlet API clone and communicates
* directly with hop applications instead of using RMI.
*/
public class AcmeServletClient extends HttpServlet {
private int uploadLimit; // limit to HTTP uploads in kB
private Hashtable apps;
private Application app;
private String cookieDomain;
private boolean debug;
static final byte HTTP_GET = 0;
static final byte HTTP_POST = 1;
public AcmeServletClient (Application app) {
this.app = app;
this.uploadLimit = 1024; // generous 1mb upload limit
}
public void init (ServletConfig config) throws ServletException {
super.init (config);
// do nothing
}
public void doGet (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
execute (request, response, HTTP_GET);
}
public void doPost (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
execute (request, response, HTTP_POST);
}
private void execute (HttpServletRequest request, HttpServletResponse response, byte method) {
String protocol = request.getProtocol ();
Cookie[] cookies = request.getCookies();
try {
RequestTrans reqtrans = new RequestTrans (method);
// read and set http parameters
for (Enumeration e = request.getParameterNames(); e.hasMoreElements(); ) {
// Params parsen
String nextKey = (String)e.nextElement();
String[] paramValues = request.getParameterValues(nextKey);
if (paramValues != null) {
reqtrans.set (nextKey, paramValues[0]); // set to single string value
if (paramValues.length > 1)
reqtrans.set (nextKey+"_array", paramValues); // set string array
}
}
// check for MIME file uploads
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);
}
}
// HACK - sessions not fully supported in Acme.Serve
// Thats ok, we dont need the session object, just the id.
reqtrans.session = request.getRequestedSessionId();
// get Cookies
if (cookies != null) {
for (int i=0; i < cookies.length;i++) try {
String nextKey = cookies[i].getName ();
String nextPart = cookies[i].getValue ();
reqtrans.set (nextKey, nextPart);
} catch (Exception badCookie) {}
}
// get optional path info
String pathInfo = request.getServletPath ();
if (pathInfo != null) {
if (pathInfo.indexOf (app.getName()) == 1)
pathInfo = pathInfo.substring (app.getName().length()+1);
reqtrans.path = trim (pathInfo);
} else
reqtrans.path = "";
// do standard HTTP variables
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);
String authorization = request.getHeader("authorization");
if ( authorization != null )
reqtrans.set ("authorization", authorization );
ResponseTrans restrans = null;
restrans = app.execute (reqtrans);
writeResponse (response, restrans, cookies, protocol);
} catch (Exception x) {
x.printStackTrace ();
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.getRedirect () != null) {
try {
res.sendRedirect(trans.getRedirect ());
} catch(Exception io_e) {}
} else {
if (!trans.cache) {
// 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
}
if ( trans.realm!=null )
res.setHeader( "WWW-Authenticate", "Basic realm=\"" + trans.realm + "\"" );
if (trans.status > 0)
res.setStatus (trans.status);
res.setContentLength (trans.getContentLength ());
res.setContentType (trans.getContentType ());
try {
OutputStream out = res.getOutputStream ();
out.write (trans.getContent ());
out.close ();
} catch(Exception io_e) { System.out.println ("Error in writeResponse: "+io_e); }
}
}
private void redirectResponse (HttpServletRequest request, HttpServletResponse res, ResponseTrans trans, String url) {
try {
res.sendRedirect(url);
} catch (Exception e) {
System.err.println ("Exception in 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;
if (contentLength > maxKbytes*1024) {
throw new RuntimeException ("Upload exceeds limit of "+maxKbytes+" kb.");
}
String contentType = request.getContentType ();
up = new Uploader(maxKbytes);
up.load (in, contentType, contentLength);
return up;
}
public Object getUploadPart(Uploader up, String name) {
return up.getParts().get(name);
}
public String getServletInfo (){
return new String("Hop ServletClient");
}
private String trim (String str) {
if (str == null)
return null;
char[] val = str.toCharArray ();
int len = val.length;
int st = 0;
while ((st < len) && (val[st] <= ' ' || val[st] == '/')) {
st++;
}
while ((st < len) && (val[len - 1] <= ' ' || val[len - 1] == '/')) {
len--;
}
return ((st > 0) || (len < val.length)) ? new String (val, st, len-st) : str;
}
}

View file

@ -0,0 +1,78 @@
// EmbeddedServletClient.java
// Copyright (c) Hannes Wallnöfer, 2002
package helma.servlet;
import javax.servlet.*;
import java.io.*;
import java.util.*;
import helma.framework.*;
import helma.framework.core.Application;
import helma.main.*;
import helma.util.*;
/**
* Servlet client that runs a Helma application for the embedded
* web server
*/
public final class EmbeddedServletClient extends AbstractServletClient {
private Application app = null;
private String appName;
// tells us whether the application is mounted as root or by its name
// depending on this we know whether we have to transform the request path
boolean root;
public EmbeddedServletClient (String appName, boolean isRoot) {
this.appName = appName;
this.root = isRoot;
}
IRemoteApp getApp (String appID) {
if (app == null)
app = Server.getServer().getApplication (appName);
return app;
}
void invalidateApp (String appID) {
// do nothing
}
String getAppID (String path) {
return appName;
}
String getRequestPath (String path) {
if (path == null)
return "";
if (root)
return trim (path);
int appInPath = path.indexOf (appName);
if (appInPath > 0)
return trim (path.substring (appInPath+appName.length()));
else
return trim (path);
}
String trim (String str) {
char[] val = str.toCharArray ();
int len = val.length;
int st = 0;
while ((st < len) && (val[st] <= ' ' || val[st] == '/'))
st++;
while ((st < len) && (val[len - 1] <= ' ' || val[len - 1] == '/'))
len--;
return ((st > 0) || (len < val.length)) ? new String (val, st, len-st) : str;
}
}

View file

@ -70,17 +70,17 @@ public class MultiServletClient extends AbstractServletClient {
int len = val.length; int len = val.length;
int st = 0; int st = 0;
// advance to start of path // advance to start of path, eating up any slashes
while ((st < len) && (val[st] <= ' ' || val[st] == '/')) while ((st < len) && (val[st] <= ' ' || val[st] == '/'))
st++; st++;
// eat characters of first path element // advance until slash ending the first path element
while (st < len && val[st] != '/') while (st < len && val[st] != '/')
st++; st++;
if (st < len && val[st] == '/') if (st < len && val[st] == '/')
st++; st++;
// eat away noise at end of path // eat away spaces and slashes at end of path
while ((st < len) && (val[len - 1] <= ' ' || val[len - 1] == '/')) while ((st < len) && (val[len - 1] <= ' ' || val[len - 1] == '/'))
len--; len--;

View file

@ -1,44 +1,36 @@
// ServletClient.java // ServletClient.java
// Copyright (c) Hannes Wallnöfer, Raphael Spannocchi 1998-2000 // Copyright (c) Hannes Wallnöfer, Raphael Spannocchi 1998-2002
/* Portierung von helma.asp.AspClient auf Servlets */
/* Author: Raphael Spannocchi Datum: 27.11.1998 */
package helma.servlet; package helma.servlet;
import javax.servlet.*; import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*; import java.io.*;
import java.rmi.Naming; import java.rmi.Naming;
import java.rmi.RemoteException; import java.rmi.RemoteException;
import java.util.*; import java.util.*;
import helma.framework.*; import helma.framework.*;
import helma.util.*;
/** /**
* This is the HOP servlet adapter. This class communicates with just * This is the standard Helma servlet adapter. This class represents a servlet
* one Hop application. * that is dedicated to one Helma application over RMI.
*/ */
public class ServletClient extends AbstractServletClient { public class ServletClient extends AbstractServletClient {
private IRemoteApp app = null; private IRemoteApp app = null;
private String appName; private String appName = null;
public void init (ServletConfig init) throws ServletException { public void init (ServletConfig init) throws ServletException {
super.init (init); super.init (init);
appName = init.getInitParameter ("application"); appName = init.getInitParameter ("application");
if (appName == null)
appName = "base";
super.init (init);
} }
IRemoteApp getApp (String appID) throws Exception { IRemoteApp getApp (String appID) throws Exception {
if (app != null) if (app != null)
return app; return app;
if (appName == null)
throw new ServletException ("Helma application name not specified for helma.servlet.ServletClient");
app = (IRemoteApp) Naming.lookup (hopUrl + appName); app = (IRemoteApp) Naming.lookup (hopUrl + appName);
return app; return app;
} }
@ -76,7 +68,7 @@ public class ServletClient extends AbstractServletClient {
// for testing // for testing
public static void main (String args[]) { public static void main (String args[]) {
AbstractServletClient client = new ServletClient (); AbstractServletClient client = new ServletClient ();
String path = "///appname/do/it/for/me///"; String path = "///appname/some/random/path///";
System.out.println (client.getAppID (path)); System.out.println (client.getAppID (path));
System.out.println (client.getRequestPath (path)); System.out.println (client.getRequestPath (path));
} }
@ -85,20 +77,3 @@ public class ServletClient extends AbstractServletClient {
} }

View file

@ -4,16 +4,15 @@
package helma.servlet; package helma.servlet;
import javax.servlet.*; import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
import helma.framework.*; import helma.framework.*;
import helma.framework.core.Application; import helma.framework.core.Application;
import helma.objectmodel.*;
import helma.util.*; import helma.util.*;
/** /**
* This is a standalone Hop servlet client, running a Hop application by itself. * Standalone servlet client that runs a Helma application all by itself
* in embedded mode without relying on helma.main.Server.
*/ */
public final class StandaloneServletClient extends AbstractServletClient { public final class StandaloneServletClient extends AbstractServletClient {
@ -22,7 +21,7 @@ public final class StandaloneServletClient extends AbstractServletClient {
private String appName; private String appName;
private String serverProps; private String serverProps;
public void init (ServletConfig init) throws ServletException { public void init (ServletConfig init) throws ServletException {
super.init (init); super.init (init);
appName = init.getInitParameter ("application"); appName = init.getInitParameter ("application");
@ -105,13 +104,11 @@ public final class StandaloneServletClient extends AbstractServletClient {
// for testing // for testing
public static void main (String args[]) { public static void main (String args[]) {
AbstractServletClient client = new ServletClient (); AbstractServletClient client = new ServletClient ();
String path = "///appname/do/it/for/me///"; String path = "///appname/some/random/path///";
System.out.println (client.getAppID (path)); System.out.println (client.getAppID (path));
System.out.println (client.getRequestPath (path)); System.out.println (client.getRequestPath (path));
} }
} }

View file

@ -1,4 +1,4 @@
// Uploader.java // FileUpload.java
// Copyright (c) Hannes Wallnöfer 1996-2000 // Copyright (c) Hannes Wallnöfer 1996-2000
package helma.util; package helma.util;
@ -8,19 +8,19 @@ import java.io.*;
import java.util.*; import java.util.*;
/** /**
* Utility class for file uploads via HTTP POST. * Utility class for MIME file uploads via HTTP POST.
*/ */
public class Uploader { public class FileUpload {
public Hashtable parts; public Hashtable parts;
int maxKbytes; int maxKbytes;
public Uploader () { public FileUpload () {
maxKbytes = 500; maxKbytes = 1024;
} }
public Uploader (int max) { public FileUpload (int max) {
maxKbytes = max; maxKbytes = max;
} }