/* basicweb.Message.java
* $Id, $Date eric Exp $
* (c) COPYRIGHT MIT and INRIA, 1997.
* Please first read the full copyright statement in file COPYRIGHT.html
*
* Light fuse and get away.
*/
package w3c.model.tools.basicweb;
import java.io.*;
import java.net.*;
import java.util.*;
import w3c.model.www.pep.PEPAgent;
import w3c.model.www.pep.PEPExtension; // for construction states
import w3c.model.www.pep.PEPMessage;
import w3c.model.www.pep.InstanceContext;
import w3c.model.www.pep.altlib.ErrorContext;
/*
Message - "The basic unit of HTTP communications" - rfc2068
extended by Request, ProxyRequest and Reply.
*/
abstract public class Message implements PEPMessage
boolean WATCH = true;
String startLine;
Hashtable headers;
Socket socket;
InputStream in;
OutputStream out;
String URI;
PEPAgent pepAgent;
InstanceContext instanceContext;
String path = null; /* real file path to get or put */
/*
The header list extends the interface in
PEPMessage.
*/
public static final int ACCEPT = 4;
public static final int CONNECTION = 5;
public static final int CONTENT_LENGTH = 6;
public static final int CONTENT_TYPE = 7;
public static final int DATE = 8;
public static final int HOST = 9;
public static final int LAST_MODIFIED = 10;
public static final int USER_AGENT = 11;
public static final int _HEADER_NAME_COUNT = 12;
final static String headerNames[] = {
"PEP",
"C-PEP",
"PEP-Info",
"C-PEP-Info",
"Accept",
"Connection",
"Content-Length",
"Content-Type",
"Date",
"Host",
"Last-Modified",
"User-Agent",
};
public final int TEXT_HTML = 0;
public final int TEXT_PLAIN = 1;
public final int _MEDIA_TYPES_COUNT = 2;
final String mediaTypes[] = {
"text/html",
"text/plain"
};
final String extensions[] = {
".html",
".txt"
};
boolean writable = false;
ErrorContext errorContext;
/* constructor for Request */
Message ( Socketsocket, InputStreamin, OutputStreamout, StringURI, PEPAgentpepAgent, ErrorContexterrorContext) {
headers = Hashtable(5, 3);
this.socket = socket;
this.in = in;
this.out = out;
this.URI = URI;
this.pepAgent = pepAgent;
this.errorContext = errorContext;
instanceContext = InstanceContext(pepAgent, this, errorContext);
}
/* constructor for Reply */
Message ( Socketsocket, InputStreamin, OutputStreamout, StringURI, Messageold) {
headers = Hashtable(5, 3);
this.socket = socket;
this.in = in;
this.out = out;
this.URI = URI;
pepAgent = old.pepAgent;
errorContext = old.errorContext;
instanceContext = InstanceContext(old.instanceContext, this);
}
public Socket getSocket () {return socket;}
public InputStream getIn () {return in;}
public void setIn ( InputStreamin) {this.in = in;}
public OutputStream getOut () {return out;}
public void setOut ( OutputStreamout) {this.out = out;}
public String getURI () {return URI;}
public void setURI ( StringURI) {this.URI = URI;}
public InstanceContext getInstanceContext () {return instanceContext;}
public void useHeaders ( Messageold) {
headers = old.headers;
}
public void setHeaderValue ( Stringname, Stringvalue) {
headers.put(name, value);
}
public void setHeaderValue ( intname, Stringvalue) {
headers.put(headerNames[name], value);
}
public void clearHeader ( Stringname) {
headers.remove(name);
}
public void clearHeader ( intname) {
headers.remove(headerNames[name]);
}
public String getHeaderValue ( Stringname) {
return ( (String)headers.get(name);
}
public String getHeaderValue ( intname) {
return ( (String)headers.get(headerNames[name]);
}
public Vector getMatchingHeaders( Stringname){
Vectorret = Vector();
if (name.endsWith("*")))
name = name.substring(0, name.length() - 1);
Enumeratione = headers.keys();
while (e.hasMoreElements())) {
Stringheader = (String)e.nextElement();
if (header.startsWith(name)))
ret.addElement(header);
}
return ret;
}
/* header support for specific fields
*/
void setMediaType( inttype) {
setHeaderValue(CONTENT_TYPE, mediaTypes[type]);
}
void setMediaTypeFor ( Stringname) {
inti;
for (i = 0; i < extensions.length; i++)) {
if (name.endsWith(extensions[i]))) {
setMediaType(i);
return;
}
}
setMediaType(TEXT_PLAIN);
}
private static String days[] = {"Sun", "Mon", "Tue", "Wed", "Thu" , "Fri", "Sat"};
private static String months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
void setHeaderDate() {
longnow = System.currentTimeMillis();
inttz = Date().getTimezoneOffset();
Dated = Date(now+(tz*60*1000));
setHeaderValue("Date", days[d.getDay()] + ", " + d.getDate() + "" + months[d.getMonth()] + "" + (d.getYear()+1900) + "" + d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds() +" GMT");
}
/* M A P P I N G */
static URL ref = null;
URL url = null;
static static {
try {
ref = URL("http://localhost/");
} catch (MalformedURLExceptionf)) {
}
}
public String getPath () {
if (path != null))
return path;
try {
url = URL(URI);
path = url.getFile();
return path;
} catch (MalformedURLExceptione)) {
try {
url = URL(ref, URI);
path = url.getFile();
return path;
} catch (MalformedURLExceptionf)) {
System.out.println("MalformedURLException: "+f.getMessage());
}
}
return null;
}
public String getMappedFile () {
if (url == null))
return URI;
try {
return URL (url, path).getFile();
} catch (MalformedURLExceptionf)) {
System.out.println("MalformedURLException: "+f.getMessage());
}
return null;
}
public String getMappedURI () {
if (url == null))
return URI;
try {
return URL (url, path).toExternalForm();
} catch (MalformedURLExceptionf)) {
System.out.println("MalformedURLException: "+f.getMessage());
}
return null;
}
public void mapURI ( Stringfrom, Stringto) {
try {
URLfromUrl = URL(from);
from = fromUrl.getFile();
} catch (MalformedURLExceptionf)) { // leave from alone
}
Stringpath = getPath();
if (!path.startsWith(from)))
return;
path = to + path.substring(from.length());
this.path = path;
}
/* R E A D I N G */
abstract boolean parseStartLine();
String readLine () {
byteb[] = byte[1024];
bytec = -1;
inti = 0;
try {
while ((c = (byte)in.read()) != 'n' && c != -1))
if (c != 'r'))
b[i++] = c;
} catch (IOExceptione)) {
}
if (c == -1 && i == 0))
return null;
return String(b, 0, 0, i);
}
boolean read () throws IOException{
/* PEP incoming CONNECT */
pepAgent.handleHeaders(instanceContext, PEPExtension.CONNECT);
while (true)) {
Stringinput = readLine();
// System.out.println("<!- reading \"" + input + "\" ->");
if (input == null))
throw IOException("fini");
if ("".equals(input)))
if (startLine == null)) /* rfc2068#4.1 */
continue;
else {
/* PEP incoming HEADERS */
pepAgent.handleHeaders(instanceContext, PEPExtension.HEADERS);
return true;
}
elseif (startLine == null)) {
startLine = input;
if (!parseStartLine()))
return false;
System.out.println("<!- reading "" + startLine + "" ->");
/* PEP incoming STARTLINE */
pepAgent.handleHeaders(instanceContext, PEPExtension.STARTLINE);
} elseif (!parseMessageHeader(input)))
return false;
}
}
boolean parseMessageHeader ( Stringinput) {
Stringvalue = null;
inti = input.indexOf(':');
if (i < 0))
return false;
if (i == 0))
setHeaderValue(input.trim(), null);
elsesetHeaderValue(input.substring(0, i).trim(), input.substring(i+1).trim());
return true;
}
/* W R I T I N G */
private void writeLine ( Stringdata) throws IOException{
byteb[] = byte[data.length() + 1];
data.getBytes(0, b.length - 1, b, 0);
b[b.length-1] = 'n';
try {
out.write(b);
} catch (IOExceptione)) {
System.err.println("<!- error writing "" + data + "" to "+out.toString()+" ->");
e.printStackTrace();
}
if (WATCH)) System.out.println("<!- writing line ->" + data);
}
void write ( Stringdata) throws IOException{
writeHeaders();
byteb[] = byte[data.length()];
data.getBytes(0, b.length, b, 0);
out.write(b);
// if (WATCH) System.out.println("<!- writing data ->" + data);
}
void write ( bytedata[]) throws IOException{
writeHeaders();
out.write(data);
// if (WATCH) System.out.println("<!- writing data ->" + new String(data, 0, 0, data.length));
}
protected void prepStartLine () {
}
void writeHeaders () throws IOException{
if (writable))
return;
/* PEP outgoing CONNECT */
pepAgent.generateHeaders(instanceContext, PEPExtension.CONNECT);
prepStartLine(); // request sets PEP- method for required extensions
if (getHeaderValue(DATE) == null))
setHeaderDate();
writeLine(startLine);
/* PEP outgoing STARTLINE */
pepAgent.generateHeaders(instanceContext, PEPExtension.STARTLINE);
// System.out.println("<!- writing \"" + startLine + "\" ->");
for (Enumerationen = headers.keys(); en.hasMoreElements();)) {
Stringname = (String)en.nextElement();
Stringvalue = (String)headers.get(name);
writeLine(name + ": " + value);
// System.out.println("<!- writing \"" + name + ": " + value + "\" ->");
}
/* PEP outgoing HEADERS */
pepAgent.generateHeaders(instanceContext, PEPExtension.NON_PEP_HEADERS);
Hashtableh = instanceContext.mayIGetYouBags();
for (Enumeratione = h.keys(); e.hasMoreElements();)) {
Objecto = e.nextElement();
Integeri = (Integer)o;
Stringvalue = (String)h.get(i);
writeLine(headerNames[i.intValue()] + ": " + value);
}
writeLine("");
pepAgent.generateHeaders(instanceContext, PEPExtension.HEADERS);
writable = true;
}
void getFile ( Filefile) throws IOException{
RandomAccessFilefileInput = RandomAccessFile(file, "r");
setHeaderValue(CONTENT_LENGTH, "" + (int)file.length());
byteb[] = byte[(int)file.length()];
fileInput.read(b);
write(b);
}
void putFile ( Filefile) throws IOException{
intlen = Integer.parseInt(getHeaderValue(CONTENT_LENGTH));
byteb[] = byte[len];
RandomAccessFilefileOutput = RandomAccessFile(file, "rw");
setHeaderValue(CONTENT_LENGTH, "" + (int)file.length());
in.read(b);
fileOutput.write(b);
}
void readRest () throws IOException{
StringvalueStr = getHeaderValue(CONTENT_LENGTH);
intlen;
if (valueStr == null || (len = Integer.parseInt(valueStr)) <= 0))
return;
byteb[] = byte[len];
in.read(b);
if (out != null))
out.write(b);
}
/* @@@ this function must exist somewhere in java already */
static int arrayFind ( Stringray[], StringlookFor) {
inti;
for (i = 0; i < ray.length; i++))
if (ray[i].equals(lookFor)))
break;
return i == ray.length ? -1 : i;
}
public InputStream getInputStream () {
return in;
}
public void setInputStream ( InputStreamin) {
this.in = in;
}
public OutputStream getOutputStream () {
return out;
}
public void setOutputStream ( OutputStreamout) {
this.out = out;
}