2000-12-29 17:57:21 +00:00
|
|
|
|
// ResponseTrans.java
|
|
|
|
|
// Copyright (c) Hannes Walln<6C>fer 1998-2000
|
|
|
|
|
|
|
|
|
|
package helma.framework;
|
|
|
|
|
|
|
|
|
|
import java.io.*;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
import helma.objectmodel.*;
|
|
|
|
|
import helma.util.*;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A Transmitter for a response to the servlet client. Objects of this
|
|
|
|
|
* class are directly exposed to JavaScript as global property res.
|
|
|
|
|
*/
|
|
|
|
|
|
2001-02-28 15:06:49 +00:00
|
|
|
|
public class ResponseTrans implements Externalizable {
|
2000-12-29 17:57:21 +00:00
|
|
|
|
|
2001-11-26 17:20:10 +00:00
|
|
|
|
/**
|
|
|
|
|
* Set the MIME content type of the response.
|
|
|
|
|
*/
|
2000-12-29 17:57:21 +00:00
|
|
|
|
public String contentType = "text/html";
|
|
|
|
|
|
2001-11-26 17:20:10 +00:00
|
|
|
|
/**
|
|
|
|
|
* Set the charset of the response.
|
|
|
|
|
*/
|
2001-05-20 13:09:42 +00:00
|
|
|
|
public String charset;
|
2000-12-29 17:57:21 +00:00
|
|
|
|
|
2001-11-26 17:20:10 +00:00
|
|
|
|
/**
|
|
|
|
|
* used to allow or disable client side caching
|
|
|
|
|
*/
|
2000-12-29 17:57:21 +00:00
|
|
|
|
public boolean cache = true;
|
|
|
|
|
|
2001-11-26 17:20:10 +00:00
|
|
|
|
/**
|
|
|
|
|
* Used for HTTP response code, if 0 code 200 OK will be used.
|
|
|
|
|
*/
|
2001-05-20 13:09:42 +00:00
|
|
|
|
public int status = 0;
|
2000-12-29 17:57:21 +00:00
|
|
|
|
|
2002-03-19 19:14:09 +00:00
|
|
|
|
/**
|
|
|
|
|
* Used for HTTP authentication
|
|
|
|
|
*/
|
|
|
|
|
public String realm;
|
2002-03-07 14:31:12 +00:00
|
|
|
|
|
2001-02-20 15:53:12 +00:00
|
|
|
|
// name of the skin to be rendered after completion, if any
|
2001-02-28 15:06:49 +00:00
|
|
|
|
public transient String skin = null;
|
2001-02-20 15:53:12 +00:00
|
|
|
|
|
2001-05-20 13:09:42 +00:00
|
|
|
|
// the actual response
|
|
|
|
|
private byte[] response = null;
|
|
|
|
|
|
|
|
|
|
// contains the redirect URL
|
2002-03-13 23:38:13 +00:00
|
|
|
|
private String redir = null;
|
2001-05-20 13:09:42 +00:00
|
|
|
|
|
|
|
|
|
// cookies
|
|
|
|
|
String cookieKeys[];
|
|
|
|
|
String cookieValues[];
|
|
|
|
|
int cookieDays[];
|
|
|
|
|
int nCookies = 0;
|
|
|
|
|
|
|
|
|
|
// the buffer used to build the response
|
|
|
|
|
private transient StringBuffer buffer = null;
|
|
|
|
|
// these are used to implement the _as_string variants for Hop templates.
|
|
|
|
|
private transient Stack buffers;
|
|
|
|
|
|
2002-03-19 19:14:09 +00:00
|
|
|
|
// the path used to resolve skin names
|
2002-05-14 16:33:24 +00:00
|
|
|
|
private transient Object skinpath = null;
|
|
|
|
|
// the processed skinpath as array of Nodes or directory names
|
|
|
|
|
private transient Object[] translatedSkinpath = null;
|
2002-03-19 19:14:09 +00:00
|
|
|
|
|
2001-11-26 17:20:10 +00:00
|
|
|
|
static final long serialVersionUID = -8627370766119740844L;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* the buffers used to build the single body parts -
|
|
|
|
|
* transient, response must be constructed before this is serialized
|
|
|
|
|
*/
|
|
|
|
|
public transient String title, head, body, message, error;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* JavaScript object to make the values Map accessible to
|
|
|
|
|
* script code as res.data
|
|
|
|
|
*/
|
|
|
|
|
public transient Object data;
|
|
|
|
|
|
|
|
|
|
// the map of form and cookie data
|
|
|
|
|
private transient Map values;
|
|
|
|
|
|
2000-12-29 17:57:21 +00:00
|
|
|
|
|
|
|
|
|
public ResponseTrans () {
|
|
|
|
|
super ();
|
2001-11-26 17:20:10 +00:00
|
|
|
|
title = head = body = message = error = null;
|
|
|
|
|
values = new HashMap ();
|
2000-12-29 17:57:21 +00:00
|
|
|
|
}
|
2001-11-26 17:20:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get a value from the responses map by key.
|
|
|
|
|
*/
|
|
|
|
|
public Object get (String name) {
|
|
|
|
|
try {
|
|
|
|
|
return values.get (name);
|
|
|
|
|
} catch (Exception x) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the data map for this response transmitter.
|
|
|
|
|
*/
|
|
|
|
|
public Map getResponseData () {
|
|
|
|
|
return values;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Reset the response object to its initial empty state.
|
|
|
|
|
*/
|
2000-12-29 17:57:21 +00:00
|
|
|
|
public void reset () {
|
|
|
|
|
if (buffer != null)
|
|
|
|
|
buffer.setLength (0);
|
2001-03-01 16:02:11 +00:00
|
|
|
|
response = null;
|
2001-05-20 13:09:42 +00:00
|
|
|
|
redir = null;
|
2001-02-28 15:06:49 +00:00
|
|
|
|
skin = null;
|
2001-11-26 17:20:10 +00:00
|
|
|
|
title = head = body = message = error = null;
|
|
|
|
|
values.clear ();
|
2000-12-29 17:57:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This is called before a template is rendered as string (xxx_as_string) to redirect the output
|
|
|
|
|
* to a new string buffer.
|
|
|
|
|
*/
|
|
|
|
|
public void pushStringBuffer () {
|
|
|
|
|
if (buffers == null)
|
|
|
|
|
buffers = new Stack();
|
|
|
|
|
if (buffer != null)
|
|
|
|
|
buffers.push (buffer);
|
|
|
|
|
buffer = new StringBuffer (128);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the content of the current string buffer and switches back to the previos one.
|
|
|
|
|
*/
|
|
|
|
|
public String popStringBuffer () {
|
|
|
|
|
StringBuffer b = buffer;
|
|
|
|
|
buffer = buffers.empty() ? null : (StringBuffer) buffers.pop ();
|
|
|
|
|
return b.toString ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Append a string to the response unchanged.
|
|
|
|
|
*/
|
|
|
|
|
public void write (Object what) {
|
|
|
|
|
if (what != null) {
|
|
|
|
|
if (buffer == null)
|
|
|
|
|
buffer = new StringBuffer (512);
|
|
|
|
|
buffer.append (what.toString ());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2001-07-31 23:58:28 +00:00
|
|
|
|
/**
|
|
|
|
|
* Utility function that appends a <br> to whatever is written
|
|
|
|
|
*/
|
|
|
|
|
public void writeln (Object what) {
|
|
|
|
|
if (buffer == null)
|
|
|
|
|
buffer = new StringBuffer (512);
|
|
|
|
|
if (what != null)
|
|
|
|
|
buffer.append (what.toString ());
|
|
|
|
|
buffer.append ("<br>\r\n");
|
|
|
|
|
}
|
|
|
|
|
|
2000-12-29 17:57:21 +00:00
|
|
|
|
/**
|
|
|
|
|
* Replace special characters with entities, including <, > and ", thus allowing
|
|
|
|
|
* no HTML tags.
|
|
|
|
|
*/
|
|
|
|
|
public void encode (Object what) {
|
|
|
|
|
if (what != null) {
|
|
|
|
|
if (buffer == null)
|
|
|
|
|
buffer = new StringBuffer (512);
|
|
|
|
|
HtmlEncoder.encodeAll (what.toString (), buffer);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Replace special characters with entities but leave <, > and ", allowing HTML tags
|
|
|
|
|
* in the response.
|
|
|
|
|
*/
|
|
|
|
|
public void format (Object what) {
|
|
|
|
|
if (what != null) {
|
|
|
|
|
if (buffer == null)
|
|
|
|
|
buffer = new StringBuffer (512);
|
|
|
|
|
HtmlEncoder.encode (what.toString (), buffer);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Replace special characters with entities, including <, > and ", thus allowing
|
|
|
|
|
* no HTML tags.
|
|
|
|
|
*/
|
|
|
|
|
public void encodeXml (Object what) {
|
|
|
|
|
if (what != null) {
|
|
|
|
|
if (buffer == null)
|
|
|
|
|
buffer = new StringBuffer (512);
|
|
|
|
|
HtmlEncoder.encodeXml (what.toString (), buffer);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2001-03-09 18:39:47 +00:00
|
|
|
|
/**
|
|
|
|
|
* Encode HTML entities, but leave newlines alone. This is for the content of textarea forms.
|
|
|
|
|
*/
|
|
|
|
|
public void encodeForm (Object what) {
|
|
|
|
|
if (what != null) {
|
|
|
|
|
if (buffer == null)
|
|
|
|
|
buffer = new StringBuffer (512);
|
|
|
|
|
HtmlEncoder.encodeAll (what.toString (), buffer, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-12-29 17:57:21 +00:00
|
|
|
|
public void append (String what) {
|
|
|
|
|
if (what != null) {
|
|
|
|
|
if (buffer == null)
|
|
|
|
|
buffer = new StringBuffer (512);
|
|
|
|
|
buffer.append (what);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void redirect (String url) throws RedirectException {
|
2001-05-20 13:09:42 +00:00
|
|
|
|
redir = url;
|
2000-12-29 17:57:21 +00:00
|
|
|
|
throw new RedirectException (url);
|
|
|
|
|
}
|
|
|
|
|
|
2001-05-20 13:09:42 +00:00
|
|
|
|
public String getRedirect () {
|
|
|
|
|
return redir;
|
|
|
|
|
}
|
|
|
|
|
|
2001-03-01 16:02:11 +00:00
|
|
|
|
/**
|
|
|
|
|
* Allow to directly set the byte array for the response. Calling this more than once will
|
|
|
|
|
* overwrite the previous output. We take a generic object as parameter to be able to
|
|
|
|
|
* generate a better error message, but it must be byte[].
|
|
|
|
|
*/
|
|
|
|
|
public void writeBinary (byte[] what) {
|
|
|
|
|
response = what;
|
|
|
|
|
}
|
|
|
|
|
|
2000-12-29 17:57:21 +00:00
|
|
|
|
|
|
|
|
|
/**
|
2001-02-26 19:28:55 +00:00
|
|
|
|
* This has to be called after writing to this response has finished and before it is shipped back to the
|
2000-12-29 17:57:21 +00:00
|
|
|
|
* web server. Transforms the string buffer into a char array to minimize size.
|
|
|
|
|
*/
|
2001-05-20 13:09:42 +00:00
|
|
|
|
public synchronized void close (String cset) throws UnsupportedEncodingException {
|
|
|
|
|
// only use default charset if not explicitly set for this response.
|
|
|
|
|
if (charset == null)
|
|
|
|
|
charset = cset;
|
|
|
|
|
|
|
|
|
|
boolean error = false;
|
2001-03-01 16:02:11 +00:00
|
|
|
|
if (response == null) {
|
|
|
|
|
if (buffer != null) {
|
2001-05-15 13:01:49 +00:00
|
|
|
|
try {
|
2001-05-20 13:09:42 +00:00
|
|
|
|
response = buffer.toString ().getBytes (charset);
|
|
|
|
|
} catch (UnsupportedEncodingException uee) {
|
|
|
|
|
error = true;
|
2001-05-15 13:01:49 +00:00
|
|
|
|
response = buffer.toString ().getBytes ();
|
|
|
|
|
}
|
2001-03-01 16:02:11 +00:00
|
|
|
|
buffer = null; // make sure this is done only once, even with more requsts attached
|
|
|
|
|
} else {
|
|
|
|
|
response = new byte[0];
|
|
|
|
|
}
|
2001-02-26 19:28:55 +00:00
|
|
|
|
}
|
|
|
|
|
notifyAll ();
|
2001-05-20 13:09:42 +00:00
|
|
|
|
// if there was a problem with the encoding, let the app know
|
|
|
|
|
if (error)
|
|
|
|
|
throw new UnsupportedEncodingException (charset);
|
2001-02-26 19:28:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* If we just attached to evaluation we call this instead of close because only the primary thread
|
|
|
|
|
* is responsible for closing the result
|
|
|
|
|
*/
|
|
|
|
|
public synchronized void waitForClose () {
|
|
|
|
|
try {
|
|
|
|
|
if (response == null)
|
|
|
|
|
wait (10000l);
|
|
|
|
|
} catch (InterruptedException ix) {}
|
2000-12-29 17:57:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-02-27 20:54:06 +00:00
|
|
|
|
public byte[] getContent () {
|
|
|
|
|
return response == null ? new byte[0] : response;
|
2000-12-29 17:57:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int getContentLength () {
|
2001-01-08 18:29:33 +00:00
|
|
|
|
if (response != null)
|
|
|
|
|
return response.length;
|
2000-12-29 17:57:21 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public String getContentType () {
|
2002-03-13 23:38:13 +00:00
|
|
|
|
if (charset != null)
|
|
|
|
|
return contentType+"; charset="+charset;
|
|
|
|
|
return contentType;
|
2000-12-29 17:57:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-05-14 16:33:24 +00:00
|
|
|
|
public void setSkinpath (Object obj) {
|
|
|
|
|
this.skinpath = obj;
|
|
|
|
|
this.translatedSkinpath = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Object getSkinpath () {
|
|
|
|
|
return skinpath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void setTranslatedSkinpath (Object[] arr) {
|
|
|
|
|
this.translatedSkinpath = arr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Object[] getTranslatedSkinpath () {
|
|
|
|
|
return translatedSkinpath;
|
|
|
|
|
}
|
|
|
|
|
|
2000-12-29 17:57:21 +00:00
|
|
|
|
public synchronized void setCookie (String key, String value) {
|
|
|
|
|
setCookie (key, value, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public synchronized void setCookie (String key, String value, int days) {
|
|
|
|
|
if (nCookies == 0) {
|
|
|
|
|
cookieKeys = new String [3];
|
|
|
|
|
cookieValues = new String [3];
|
|
|
|
|
cookieDays = new int [3];
|
|
|
|
|
}
|
|
|
|
|
if (nCookies == cookieKeys.length) {
|
|
|
|
|
String nk[] = new String [nCookies+3];
|
|
|
|
|
System.arraycopy (cookieKeys, 0, nk, 0, nCookies);
|
|
|
|
|
String nv[] = new String [nCookies+3];
|
|
|
|
|
System.arraycopy (cookieValues, 0, nv, 0, nCookies);
|
|
|
|
|
int nd[] = new int [nCookies+3];
|
|
|
|
|
System.arraycopy (cookieDays, 0, nd, 0, nCookies);
|
|
|
|
|
cookieKeys = nk;
|
|
|
|
|
cookieValues = nv;
|
|
|
|
|
cookieDays = nd;
|
|
|
|
|
}
|
|
|
|
|
cookieKeys [nCookies] = key;
|
|
|
|
|
cookieValues [nCookies] = value;
|
|
|
|
|
cookieDays [nCookies] = days;
|
|
|
|
|
nCookies += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void resetCookies () {
|
|
|
|
|
nCookies = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int countCookies () {
|
|
|
|
|
return nCookies;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int getDaysAt (int i) {
|
|
|
|
|
return cookieDays[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public String getKeyAt (int i) {
|
|
|
|
|
return cookieKeys[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public String getValueAt (int i) {
|
|
|
|
|
return cookieValues[i];
|
|
|
|
|
}
|
|
|
|
|
|
2001-02-28 15:06:49 +00:00
|
|
|
|
public void readExternal (ObjectInput s) throws ClassNotFoundException, IOException {
|
|
|
|
|
contentType = (String) s.readObject ();
|
|
|
|
|
response = (byte[]) s.readObject ();
|
2001-05-20 13:09:42 +00:00
|
|
|
|
redir = (String) s.readObject ();
|
2001-02-28 15:06:49 +00:00
|
|
|
|
cookieKeys = (String[]) s.readObject ();
|
|
|
|
|
cookieValues = (String[]) s.readObject ();
|
|
|
|
|
cookieDays = (int[]) s.readObject ();
|
|
|
|
|
nCookies = s.readInt ();
|
|
|
|
|
cache = s.readBoolean ();
|
2001-05-20 13:09:42 +00:00
|
|
|
|
status = s.readInt ();
|
2002-03-07 14:31:12 +00:00
|
|
|
|
realm = (String) s.readObject ();
|
2001-02-28 15:06:49 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void writeExternal (ObjectOutput s) throws IOException {
|
|
|
|
|
s.writeObject (contentType);
|
|
|
|
|
s.writeObject (response);
|
2001-05-20 13:09:42 +00:00
|
|
|
|
s.writeObject (redir);
|
2001-02-28 15:06:49 +00:00
|
|
|
|
s.writeObject (cookieKeys);
|
|
|
|
|
s.writeObject (cookieValues);
|
|
|
|
|
s.writeObject (cookieDays);
|
|
|
|
|
s.writeInt (nCookies);
|
|
|
|
|
s.writeBoolean (cache);
|
2001-05-20 13:09:42 +00:00
|
|
|
|
s.writeInt (status);
|
2002-03-07 14:31:12 +00:00
|
|
|
|
s.writeObject (realm);
|
2001-02-28 15:06:49 +00:00
|
|
|
|
}
|
2000-12-29 17:57:21 +00:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|