KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > help > internal > webapp > servlet > FilterHTMLHeadAndBodyOutputStream


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.help.internal.webapp.servlet;
13
14 import java.io.ByteArrayInputStream JavaDoc;
15 import java.io.ByteArrayOutputStream JavaDoc;
16 import java.io.FilterOutputStream JavaDoc;
17 import java.io.IOException JavaDoc;
18 import java.io.OutputStream JavaDoc;
19
20 import org.eclipse.help.internal.search.HTMLDocParser;
21
22 /**
23  * Filters output stream and inserts specified bytes before the end of HEAD
24  * element (before </html> tag) and immediately after the BODY
25  * element tag of HTML in the stream.
26  */

27 public class FilterHTMLHeadAndBodyOutputStream extends FilterOutputStream JavaDoc {
28     private static final int STATE_START = 0;
29
30     private static final int STATE_LT = 1;
31
32     private static final int STATE_LT_SLASH = 2;
33
34     private static final int STATE_LT_SLASH_H = 3;
35
36     private static final int STATE_LT_SLASH_HE = 4;
37
38     private static final int STATE_LT_SLASH_HEA = 5;
39
40     private static final int STATE_LT_SLASH_HEAD = 6;
41
42     private static final int STATE_AFTER_HEAD = 7;
43
44     private static final int STATE_LT_B = 8;
45
46     private static final int STATE_LT_BO = 9;
47
48     private static final int STATE_LT_BOD = 10;
49
50     private static final int STATE_LT_BODY = 11;
51
52     private static final int STATE_DONE = 17;
53     
54     private static final int STATE_LT_M = 18;
55     private static final int STATE_LT_ME = 19;
56     private static final int STATE_LT_MET = 20;
57     private static final int STATE_LT_META = 21;
58
59     private int areaState = STATE_START;
60
61     private int state = STATE_START;
62
63     private byte[] toHead;
64
65     private String JavaDoc bodyContent;
66     
67     private String JavaDoc charset;
68
69     ByteArrayOutputStream JavaDoc buffer = new ByteArrayOutputStream JavaDoc(7);
70
71     /**
72      * Constructor.
73      *
74      * @param out
75      * sink output stream
76      * @param bytesForHead
77      * bytes to insert at the end of head of HTML or
78      * <code>null</code>
79      * @param bytesToInsert
80      * bytes to insert at the begining of body of HTML or
81      * <code>null</code>
82      * @param bytesToAppend
83      * bytes to append at the end of body of HTML or
84      * <code>null</code>
85      */

86     public FilterHTMLHeadAndBodyOutputStream(OutputStream JavaDoc out,
87             byte[] bytesForHead, String JavaDoc bodyContent) {
88         super(out);
89         toHead = bytesForHead;
90         this.bodyContent = bodyContent;
91     }
92
93     /**
94      * Writes the specified <code>byte</code> to this output stream.
95      * <p>
96      * The underlying stream might have a more bytes written to it, following
97      * the &lt;head&gt; HTML element.
98      * <p>
99      * Implements the abstract <tt>write</tt> method of <tt>OutputStream</tt>.
100      *
101      * @param b
102      * the <code>byte</code>.
103      * @exception IOException
104      * if an I/O error occurs.
105      */

106     public final void write(int b) throws IOException JavaDoc {
107         switch (state) {
108         case STATE_START:
109         case STATE_AFTER_HEAD:
110             if (b == '<') {
111                 buffer.write(b);
112                 state = STATE_LT;
113             } else {
114                 out.write(b);
115             }
116             break;
117         case STATE_LT:
118             buffer.write(b);
119             if (b == '/') {
120                 state = STATE_LT_SLASH;
121             } else if (b == 'b' || b == 'B') {
122                 state = STATE_LT_B;
123             } else if (b == 'm' || b== 'M') {
124                 state = STATE_LT_M;
125             } else {
126                 reset();
127             }
128             break;
129         case STATE_LT_M:
130             buffer.write(b);
131             if (b == 'e' || b=='E') {
132                 state = STATE_LT_ME;
133             }
134             else {
135                 reset();
136             }
137             break;
138         case STATE_LT_ME:
139             buffer.write(b);
140             if (b == 't' || b=='T') {
141                 state = STATE_LT_MET;
142             }
143             else {
144                 reset();
145             }
146             break;
147         case STATE_LT_MET:
148             buffer.write(b);
149             if (b == 'a' || b=='A') {
150                 state = STATE_LT_META;
151             }
152             else {
153                 reset();
154             }
155             break;
156         case STATE_LT_META:
157             buffer.write(b);
158             if (b=='>') {
159                 parseMetaTag(buffer);
160                 reset();
161             }
162             break;
163         case STATE_LT_B:
164             buffer.write(b);
165             if (b == 'o' || b == 'O') {
166                 state = STATE_LT_BO;
167             } else {
168                 reset();
169             }
170             break;
171         case STATE_LT_BO:
172             buffer.write(b);
173             if (b == 'd' || b == 'D') {
174                 state = STATE_LT_BOD;
175             } else {
176                 reset();
177             }
178             break;
179         case STATE_LT_BOD:
180             buffer.write(b);
181             if (b == 'y' || b == 'Y') {
182                 state = STATE_LT_BODY;
183             } else {
184                 reset();
185             }
186             break;
187         case STATE_LT_BODY:
188             buffer.write(b);
189             if (b == '>') {
190                 out.write(buffer.toByteArray());
191                 buffer.reset();
192                 if (bodyContent != null) {
193                     out.write('\n');
194                     byte [] bytes = bodyContent.getBytes(charset!=null?charset:"UTF-8"); //$NON-NLS-1$
195
out.write(bytes);
196                     out.write('\n');
197                 }
198                 areaState = STATE_DONE;
199                 state = STATE_DONE;
200             }
201             break;
202         case STATE_LT_SLASH:
203             buffer.write(b);
204             if (b == 'h' || b == 'H') {
205                 state = STATE_LT_SLASH_H;
206             } else {
207                 reset();
208             }
209             break;
210         case STATE_LT_SLASH_H:
211             buffer.write(b);
212             if (b == 'e' || b == 'E') {
213                 state = STATE_LT_SLASH_HE;
214             } else {
215                 reset();
216             }
217             break;
218         case STATE_LT_SLASH_HE:
219             buffer.write(b);
220             if (b == 'a' || b == 'A') {
221                 state = STATE_LT_SLASH_HEA;
222             } else {
223                 reset();
224             }
225             break;
226         case STATE_LT_SLASH_HEA:
227             buffer.write(b);
228             if (b == 'd' || b == 'D') {
229                 state = STATE_LT_SLASH_HEAD;
230             } else {
231                 reset();
232             }
233             break;
234         case STATE_LT_SLASH_HEAD:
235             buffer.write(b);
236             if (b == '>') {
237                 if (toHead != null) {
238                     out.write(toHead);
239                     out.write('\n');
240                 }
241                 areaState = STATE_AFTER_HEAD;
242                 state = STATE_AFTER_HEAD;
243                 out.write(buffer.toByteArray());
244                 buffer.reset();
245             } else {
246                 reset();
247             }
248             break;
249         default: // (case STATE_DONE):
250
out.write(b);
251             break;
252         }
253     }
254     
255     private void parseMetaTag(ByteArrayOutputStream JavaDoc buffer) {
256         ByteArrayInputStream JavaDoc is = new ByteArrayInputStream JavaDoc(buffer.toByteArray());
257         String JavaDoc value = HTMLDocParser.getCharsetFromHTML(is);
258         try {
259             is.close();
260         }
261         catch (IOException JavaDoc e) {
262         }
263         if (value!=null)
264             this.charset = value;
265     }
266
267     private void reset() throws IOException JavaDoc {
268         out.write(buffer.toByteArray());
269         buffer.reset();
270         state = areaState;
271     }
272
273     public void write(byte b[], int off, int len) throws IOException JavaDoc {
274         if (state == STATE_DONE) {
275             out.write(b, off, len);
276         } else {
277             for (int i = 0; i < len; i++) {
278                 write(b[off + i]);
279             }
280         }
281     }
282
283     /*
284      * (non-Javadoc)
285      *
286      * @see java.io.FilterOutputStream#close()
287      */

288     public void close() throws IOException JavaDoc {
289         reset();
290         super.close();
291     }
292 }
293
Popular Tags