KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > freecs > content > ContentContainer


1 /**
2  * Copyright (C) 2003 Manfred Andres
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */

18
19 /**
20  * The ContentContainer is used for delivering the entry-page, error-page, ...
21  */

22 package freecs.content;
23
24 import freecs.*;
25 import freecs.interfaces.*;
26 import freecs.layout.*;
27 import freecs.util.HttpDateParser;
28
29 import java.nio.charset.Charset JavaDoc;
30 import java.nio.charset.CharacterCodingException JavaDoc;
31 import java.nio.ByteBuffer JavaDoc;
32 import java.nio.CharBuffer JavaDoc;
33
34
35 public class ContentContainer implements IResponseHeaders, IContainer {
36    private ByteBuffer JavaDoc buf;
37    private TemplateSet ts;
38    private String JavaDoc tName;
39    private Template tpl;
40    private String JavaDoc cookie,
41                         contentType="text/html";
42    
43    private String JavaDoc eTag;
44    private boolean notModified=false;
45
46    private volatile boolean chunkedHdr,
47                         nocache=false,
48                         nostore=false,
49                         keepAlive = false,
50                         isMessages = false,
51                         isRedirect,
52                         isHTTP11=true;
53
54     private short resCode = 200;
55     
56    public ContentContainer () {
57        if (Server.TRACE_CREATE_AND_FINALIZE)
58            Server.log (this, "++++++++++++++++++++++++++++++++++++++++CREATE", Server.MSG_STATE, Server.LVL_VERY_VERBOSE);
59    }
60
61     /**
62      * wraps the cntnt param into a fully http-response with the wanted headerfields
63      * @param cntnt
64      */

65    public void wrap (String JavaDoc cntnt) {
66        wrap(cntnt, null);
67    }
68    public void wrap (String JavaDoc cntnt, String JavaDoc eTag) {
69        StringBuffer JavaDoc sb = new StringBuffer JavaDoc ();
70        sb.append (isHTTP11 ? "HTTP/1.1" : "HTTP/1.0");
71        switch (resCode) {
72         case OK_CODE:
73             sb.append (OK_HDR);
74             break;
75         case REDIRECT_CODE:
76             setRedirectTo (cntnt);
77             break;
78         case NOCONTENT_CODE:
79             sb.append (NOCONTENT_HDR);
80             prepareForSending (CharBuffer.wrap(sb.toString()));
81             return;
82         case AUTHENTICATE_CODE:
83             sb.append (AUTHENTICATE_HDR);
84             contentType="text/html";
85             break;
86         case NOTFOUND_CODE:
87             sb.append (NOTFOUND_HDR);
88             contentType="text/html";
89             break;
90         }
91         sb.append ("Content-Type: ");
92         sb.append (contentType);
93         sb.append ("; charset=");
94         sb.append (Server.srv.DEFAULT_CHARSET);
95         if (nocache) {
96             sb.append ("\r\nPragma: no-cache\r\nCache-Control: no-cache");
97             sb.append ("\r\nExpires: Thu, 01 Dec 1994 16:00:00 GMT");
98         }
99         if (nostore) {
100             sb.append ("\r\nCache-Control: no-store");
101         }
102         if (eTag != null) {
103             sb.append ("\r\nETag: \"").append(eTag).append("\"");
104             //Server.log (this, "sending eTag: " + eTag, Server.MSG_STATE, Server.LVL_MAJOR);
105
}
106
107         sb = appendCookie (sb);
108
109         if (!isHTTP11 || !keepAlive || isMessages) {
110             sb.append ("\r\nConnection: close\r\nProxy-Connection: close");
111         } else {
112             sb.append ("\r\nConnection: Keep-Alive\r\nProxy-Connection: Keep-Alive");
113             if (!chunkedHdr) {
114                 sb.append("\r\nContent-Length: ");
115                 sb.append (cntnt.length ());
116             }
117         }
118         if (chunkedHdr) {
119             sb.append ("\r\nTransfer-Encoding: chunked\r\n\r\n");
120             sb.append (Integer.toHexString (cntnt.length ()));
121             sb.append ("\r\n");
122             sb.append (cntnt);
123             sb.append ("\r\n");
124             prepareForSending(CharBuffer.wrap (sb.toString()));
125             return;
126         }
127         sb.append ("\r\n\r\n");
128         if ("iso-8859-1".equals(Server.srv.DEFAULT_CHARSET)) {
129             sb.append(cntnt);
130             prepareForSending(CharBuffer.wrap(sb.toString()));
131         } else {
132             CharBuffer JavaDoc hdrChar = CharBuffer.wrap(sb.toString());
133             prepareForSending(hdrChar, CharBuffer.wrap (cntnt));
134         }
135    }
136    
137    /**
138     * sets the HTTP-Response-Code
139     * @param code
140     */

141    public void setResCode (short code) {
142         resCode=code;
143    }
144
145     /**
146      * append the cookie-header-field to the given StringBuffer
147      * @param sb the stringbuffer to append the cookie-header-field
148      * @return the stringbuffer with the cookie-header-field appended
149      */

150    public StringBuffer JavaDoc appendCookie (StringBuffer JavaDoc sb) {
151       if (cookie == null) return sb;
152       sb.append ("\r\n");
153       sb.append ("Set-Cookie: FreeCSSession=");
154       sb.append (cookie);
155       sb.append ("; path=/;");
156       if (Server.srv.COOKIE_DOMAIN != null) {
157         sb.append (" Domain=");
158         sb.append (Server.srv.COOKIE_DOMAIN);
159       }
160       return sb;
161    }
162
163    /**
164     * causes this content-container to use a specific template-set
165     * @param ts the template-set to use
166     */

167    public void useTemplateSet (TemplateSet ts) {
168       this.ts = ts;
169    }
170
171     /**
172      * set the template to be rendered for this content-container
173      * @param tName the name of the template
174      */

175    public void setTemplate (String JavaDoc tName) {
176       this.tName = tName;
177    }
178
179     /**
180      * renders the template and wraps it to a full httpresponse
181      */

182    public void renderTemplate (IRequest req) {
183       if (tpl == null) {
184          if (this.ts == null)
185              ts = Server.srv.templatemanager.getTemplateSet ("default");
186          tpl = ts.getTemplate (tName);
187          if (tpl == null)
188              tpl = ts.getTemplate ("not_found");
189       }
190       if (tpl.isRedirect ()) {
191          this.setRedirectTo(tpl.getDestination ());
192          return;
193       }
194       if (!nocache && !nostore &&
195               !tpl.hasToBeRendered(req.getProperty("if-none-match"),
196               HttpDateParser.parseDate(req.getProperty("if-modified-since")))) {
197           StringBuffer JavaDoc sb = new StringBuffer JavaDoc ();
198           sb.append (isHTTP11 ? "HTTP/1.1" : "HTTP/1.0");
199           sb.append (IResponseHeaders.NOT_MODIFIED);
200           prepareForSending(CharBuffer.wrap (sb.toString()));
201           return;
202       }
203       String JavaDoc cntnt = tpl.render (req);
204       if (cntnt==null || cntnt.length () < 1) {
205          Server.log (this, "renderTemplate: rendered template has no content", Server.MSG_STATE, Server.LVL_MAJOR);
206          resCode=NOCONTENT_CODE;
207          StringBuffer JavaDoc sb = new StringBuffer JavaDoc ();
208          sb.append ("<html><body><b>The requested page could not be displayed!<br><br>Reason:</b> ");
209          if (tpl == null) {
210              sb.append ("No template given");
211          } else {
212              sb.append ("Template '");
213              sb.append (tpl.getName());
214              sb.append ("' has not been found on this server.");
215          }
216          sb.append ("</body></html>");
217          wrap (sb.toString());
218          return;
219       }
220       nocache=tpl.notCacheable();
221 // if (nocache)
222
// Server.log (this, "not cacheable", Server.MSG_STATE, Server.LVL_VERY_VERBOSE);
223
wrap (cntnt, tpl.getEtag());
224    }
225
226     /**
227      * causes the response to be a chunked response
228      * the calling method has to care, that the other chunks are sent correctly
229      */

230    public void useChunkedHeader () {
231       chunkedHdr = true;
232       keepAlive = true;
233    }
234
235     /**
236      * set/unset the keep-alive header field
237      * @param b
238      */

239    public void setKeepAlive (boolean b) {
240       keepAlive = b;
241    }
242
243     /**
244      * mark this http-response as http11(true)/http10(false)
245      * @param b
246      */

247    public void setHTTP11 (boolean b) {
248       isHTTP11 = b;
249       keepAlive = true;
250    }
251
252     /**
253      * check if this response is a HTTP11 response
254      * @return boolean true if response is a HTTP11 response, false if not
255      */

256    public boolean isHttp11 () {
257       return isHTTP11;
258    }
259
260     /**
261      * set the cookievalue to append to the response-header-fields
262      * @param cookie
263      */

264    public void setCookie (String JavaDoc cookie) {
265       this.cookie = cookie;
266    }
267
268     /**
269      * return the bytebuffer which is ready to send
270      */

271    public ByteBuffer JavaDoc getByteBuffer () {
272       return buf;
273    }
274
275    /**
276     * return the content type setting
277     */

278    public String JavaDoc getContentType() {
279       return contentType;
280    }
281
282    /**
283     * set the content type setting
284     */

285    public void setContentType(String JavaDoc contentType) {
286       this.contentType = contentType;
287    }
288    
289     /**
290      * prepares the response for sending
291      * if a template is set, it will be rendered
292      * if no charbuffer is present, even after rendering the template,
293      * there is nothing to send and prepareForSending will just return
294      */

295    public void prepareForSending (CharBuffer JavaDoc cb) {
296        if (cb == null || cb.length() < 1)
297            return;
298        try {
299            buf = Charset.forName ("iso-8859-1").newEncoder().encode(cb);
300            return;
301        } catch (CharacterCodingException JavaDoc cce) {
302            Server.debug (this, "prepareForSending: ", cce, Server.MSG_ERROR, Server.LVL_MINOR);
303        }
304    }
305    
306    public void prepareForSending (CharBuffer JavaDoc hdr, CharBuffer JavaDoc cntnt) {
307        if (hdr == null || hdr.capacity() < 1)
308            return;
309        try {
310            ByteBuffer JavaDoc hdrBytes = Charset.forName("iso-8859-1").newEncoder().encode(hdr);
311            ByteBuffer JavaDoc cntntBytes = Charset.forName (Server.srv.DEFAULT_CHARSET).newEncoder().encode(cntnt);
312            buf = ByteBuffer.allocate(hdrBytes.capacity() + cntntBytes.capacity());
313            buf.put(hdrBytes);
314            buf.put(cntntBytes);
315            buf.flip();
316        } catch (Exception JavaDoc e) {
317            Server.debug (this, "Exception during prepareForSending(hdr/cntnt)", e, Server.MSG_ERROR, Server.LVL_MAJOR);
318        }
319    }
320
321
322     public boolean prepareForSending (IRequest req) {
323         if (tName != null || tpl != null)
324             renderTemplate (req);
325         if (buf == null)
326             return false;
327         return true;
328     }
329     
330     public void setContent (byte[] cntnt) throws Exception JavaDoc {
331         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
332         sb.append (isHTTP11 ? "HTTP/1.1" : "HTTP/1.0");
333         sb.append (OK_HDR);
334         sb.append ("Content-Type: ");
335         sb.append (contentType);
336         if (!isHTTP11 || !keepAlive || isMessages) {
337             sb.append ("\r\nConnection: close\r\nProxy-Connection: close");
338         } else {
339             sb.append ("\r\nConnection: Keep-Alive\r\nProxy-Connection: Keep-Alive");
340             sb.append("\r\nContent-Length: ");
341             sb.append (cntnt.length);
342         }
343         sb.append ("\r\n\r\n");
344         CharBuffer JavaDoc cb = CharBuffer.wrap (sb.toString());
345         ByteBuffer JavaDoc tempBuffer;
346         try {
347             tempBuffer = Charset.forName ("iso-8859-1").newEncoder().encode(cb);
348         } catch (CharacterCodingException JavaDoc cce) {
349             Server.debug (this, "prepareForSending: ", cce, Server.MSG_ERROR, Server.LVL_MINOR);
350             try {
351                 tempBuffer = ByteBuffer.wrap (cb.toString().getBytes(Server.srv.DEFAULT_CHARSET));
352             } catch (Exception JavaDoc e) {
353                Server.debug (this, "prepareForSending: ", e, Server.MSG_ERROR, Server.LVL_MAJOR);
354                throw e;
355             }
356         }
357         this.buf = ByteBuffer.allocate(tempBuffer.capacity() + cntnt.length);
358         this.buf.put(tempBuffer.array());
359         this.buf.put(cntnt);
360         this.buf.flip();
361     }
362
363    public boolean hasContent () {
364       return (buf != null);
365    }
366
367    public boolean closeSocket () {
368       return (!isHTTP11 || !keepAlive) && !isMessages;
369    }
370    public void setIsMessages () {
371       this.isMessages = true;
372    }
373    public void setNoCache () {
374       nocache = true;
375    }
376    public void setNoStore () {
377       nostore = true;
378    }
379
380    /**
381     * construct a HTTP-Redirect-Response
382     *
383     * @param dest the destination to redirect to
384     */

385     public void setRedirectTo(String JavaDoc dest) {
386         StringBuffer JavaDoc cntnt = new StringBuffer JavaDoc();
387         cntnt.append("<html><head><title>redirection</title><head><body>Redirected to <a HREF=\"");
388         cntnt.append(dest);
389         cntnt.append("\">");
390         cntnt.append(dest);
391         cntnt.append("</a>");
392         cntnt.append("</body></html>");
393         int len = cntnt.length();
394         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
395         sb.append(isHTTP11 ? "HTTP/1.1" : "HTTP/1.0");
396         sb.append(REDIRECT_HDR);
397         sb.append(Server.srv.DEFAULT_CHARSET);
398         sb.append("\r\nLocation: ");
399         sb.append(dest);
400         sb.append("\r\nContent-Length: ");
401         sb.append(len);
402         sb = appendCookie(sb);
403         sb.append("\r\n\r\n");
404         if ("iso-8859-1".equals(Server.srv.DEFAULT_CHARSET)) {
405             sb.append(cntnt);
406             prepareForSending(CharBuffer.wrap(sb.toString()));
407         } else {
408             CharBuffer JavaDoc hdrChar = CharBuffer.wrap(sb.toString());
409             prepareForSending(hdrChar, CharBuffer.wrap(cntnt));
410         }
411         isRedirect = true;
412     }
413   
414     public void finalize() {
415         if (Server.TRACE_CREATE_AND_FINALIZE)
416             Server.log(this, "----------------------------------------FINALIZED", Server.MSG_STATE, Server.LVL_VERY_VERBOSE);
417     }
418 }
Popular Tags