001: // AsIsFrame.java
002: // $Id: AsIsFrame.java,v 1.1 2001/04/12 14:05:54 ylafon Exp $
003: // (c) COPYRIGHT MIT, INRIA and Keio, 2001.
004: // Please first read the full copyright statement in file COPYRIGHT.html
005:
006: package org.w3c.jigsaw.frames;
007:
008: import java.io.File;
009: import java.io.FileInputStream;
010: import java.io.FileNotFoundException;
011: import java.io.IOException;
012:
013: import java.util.Enumeration;
014:
015: import org.w3c.tools.resources.ProtocolException;
016: import org.w3c.tools.resources.ResourceException;
017:
018: import org.w3c.tools.resources.event.AttributeChangedEvent;
019:
020: import org.w3c.util.CountInputStream;
021:
022: import org.w3c.www.mime.MimeParser;
023: import org.w3c.www.mime.MimeParserException;
024:
025: import org.w3c.www.http.ByteRangeOutputStream;
026: import org.w3c.www.http.HTTP;
027: import org.w3c.www.http.HeaderDescription;
028: import org.w3c.www.http.HeaderValue;
029: import org.w3c.www.http.MimeParserReplyFactory;
030: import org.w3c.www.http.HttpContentRange;
031: import org.w3c.www.http.HttpEntityTag;
032: import org.w3c.www.http.HttpRange;
033: import org.w3c.www.http.HttpReplyMessage;
034: import org.w3c.www.http.HttpFactory;
035:
036: import org.w3c.jigsaw.http.Reply;
037: import org.w3c.jigsaw.http.Request;
038:
039: /**
040: * Read the HTTP reply directly from a file. Like in Apache mod_asis
041: * http://httpd.apache.org/docs/mod/mod_asis.html
042: *
043: */
044: public class AsIsFrame extends HTTPFrame {
045:
046: // the file offset
047: int foffset = -1;
048: HttpReplyMessage asisreply = null;
049:
050: /**
051: * Listen its resource.
052: */
053: public void attributeChanged(AttributeChangedEvent evt) {
054: super .attributeChanged(evt);
055: asisreply = null;
056: }
057:
058: /**
059: * shadows the call from HTTPFrame
060: * It updates the cached headers for the automagic reply generation
061: */
062: protected void updateCachedHeaders() {
063: super .updateCachedHeaders();
064: if (asisreply == null) {
065: if (fresource != null) {
066: // read the reply from the file stream
067: FileInputStream fis = null;
068: try {
069: fis = new FileInputStream(fresource.getFile());
070: } catch (FileNotFoundException fex) {
071: // should never happen
072: }
073: CountInputStream cis = new CountInputStream(fis);
074: MimeParserReplyFactory repfact = new MimeParserReplyFactory();
075: MimeParser mp = new MimeParser(cis, repfact);
076: try {
077: asisreply = (HttpReplyMessage) mp.parse();
078: } catch (MimeParserException mex) {
079: // probably a "normal" file, serve it as-is...
080: return;
081: } catch (IOException ioex) {
082: // silently fail, iot will fail later anyway
083: return;
084: }
085: // update the offset and the Content-Length
086: foffset = (int) cis.getBytesRead();
087: try {
088: cis.close();
089: } catch (IOException ioex) {
090: }
091: ;
092: int cl = fresource.getFileLength();
093: cl -= foffset;
094: setValue(ATTR_CONTENT_LENGTH, new Integer(cl));
095: contentlength = HttpFactory.makeInteger(cl);
096: // reset the md5, as we don't yet compute it
097: md5Digest = null;
098: }
099: }
100: }
101:
102: /**
103: * Create a reply to answer to request on this file.
104: * This method will create a suitable reply (matching the given request)
105: * and will set all its default header values to the appropriate
106: * values.
107: * The Status is ignored as it is superceded byt the Asis file
108: * @param request The request to make a reply for.
109: * @return An instance of Reply, suited to answer this request.
110: */
111: public Reply createDefaultReply(Request request, int status) {
112: if (asisreply == null) {
113: updateCachedHeaders();
114: }
115: if (asisreply == null) {
116: // not parsed, try to serve it as a normal file
117: return super .createDefaultReply(request, status);
118: }
119: // create the reply with the parsed status
120: Reply reply = super .createDefaultReply(request, asisreply
121: .getStatus());
122: reply.setReason(asisreply.getReason());
123: // and update all defined headers
124: Enumeration e = asisreply.enumerateHeaderDescriptions();
125: while (e.hasMoreElements()) {
126: HeaderDescription d = (HeaderDescription) e.nextElement();
127: HeaderValue v = asisreply.getHeaderValue(d);
128: if (v != null)
129: reply.setHeaderValue(d, v);
130: }
131: return reply;
132: }
133:
134: /**
135: * Create the reply relative to the given file.
136: * @param request the incomming request.
137: * @return A Reply instance
138: * @exception ProtocolException If processsing the request failed.
139: * @exception ResourceException If the resource got a fatal error.
140: */
141: protected Reply createFileReply(Request request)
142: throws ProtocolException, ResourceException {
143: File file = fresource.getFile();
144: Reply reply = null;
145: // Won't check for range request, as we don't control the status
146: // Default to full reply then
147: reply = createDefaultReply(request, HTTP.OK);
148: try {
149: FileInputStream fis = new FileInputStream(file);
150: // and escape the headers
151: fis.skip(foffset);
152: reply.setStream(fis);
153: } catch (IOException ex) {
154: Reply error = request.makeReply(HTTP.SERVICE_UNAVAILABLE);
155: error.setContent(ex.getMessage());
156: return error;
157: }
158: return reply;
159: }
160: }
|