001: package com.opensymphony.module.sitemesh.html;
002:
003: import com.opensymphony.module.sitemesh.html.tokenizer.TagTokenizer;
004: import com.opensymphony.module.sitemesh.html.tokenizer.TokenHandler;
005: import com.opensymphony.module.sitemesh.html.util.CharArray;
006: import com.opensymphony.module.sitemesh.util.CharArrayWriter;
007:
008: import java.io.Reader;
009: import java.io.Writer; //import java.io.CharArrayWriter;
010: import java.io.IOException;
011:
012: public class HTMLProcessor {
013:
014: private final char[] in;
015: private final CharArray out;
016: private final State defaultState = new State();
017:
018: private State currentState = defaultState;
019: private Writer outStream;
020:
021: public HTMLProcessor(char[] in, CharArray out) {
022: this .in = in;
023: this .out = out;
024: }
025:
026: public HTMLProcessor(Reader in, Writer out) throws IOException {
027: CharArrayWriter inBuffer = new CharArrayWriter();
028: char[] buffer = new char[2048];
029: int n;
030: while (-1 != (n = in.read(buffer))) {
031: inBuffer.write(buffer, 0, n);
032: }
033: this .in = inBuffer.toCharArray();
034: this .out = new CharArray(2048);
035: this .outStream = out;
036: }
037:
038: public State defaultState() {
039: return defaultState;
040: }
041:
042: /**
043: * Equivalent of htmlProcessor.defaultState().addRule()
044: */
045: public void addRule(TagRule rule) {
046: defaultState.addRule(rule);
047: }
048:
049: public void process() throws IOException {
050: TagTokenizer tokenizer = new TagTokenizer(in);
051: final HTMLProcessorContext context = new HTMLProcessorContext() {
052: public State currentState() {
053: return currentState;
054: }
055:
056: public void changeState(State newState) {
057: currentState = newState;
058: }
059:
060: private CharArray[] buffers = new CharArray[10];
061: private int size;
062:
063: public void pushBuffer(CharArray buffer) {
064: if (size == buffers.length) {
065: CharArray[] newBuffers = new CharArray[buffers.length * 2];
066: System.arraycopy(buffers, 0, newBuffers, 0,
067: buffers.length);
068: buffers = newBuffers;
069: }
070: buffers[size++] = buffer;
071: }
072:
073: public CharArray currentBuffer() {
074: return buffers[size - 1];
075: }
076:
077: public CharArray popBuffer() {
078: CharArray last = buffers[size - 1];
079: buffers[--size] = null;
080: return last;
081: }
082:
083: public void mergeBuffer() {
084: CharArray top = buffers[size - 1];
085: CharArray nextDown = buffers[size - 2];
086: nextDown.append(top);
087: }
088: };
089: context.pushBuffer(out);
090: tokenizer.start(new TokenHandler() {
091:
092: public boolean shouldProcessTag(String name) {
093: return currentState
094: .shouldProcessTag(name.toLowerCase());
095: }
096:
097: public void tag(Tag tag) {
098: TagRule tagRule = currentState.getRule(tag.getName()
099: .toLowerCase());
100: tagRule.setContext(context);
101: tagRule.process(tag);
102: }
103:
104: public void text(Text text) {
105: currentState.handleText(text, context);
106: }
107:
108: public void warning(String message, int line, int column) {
109: // TODO
110: // System.out.println(line + "," + column + ": " + message);
111: }
112: });
113: defaultState.endOfState();
114: if (outStream != null) {
115: outStream.write(out.toString());
116: }
117: }
118:
119: public void addTextFilter(TextFilter textFilter) {
120: currentState.addTextFilter(textFilter);
121: }
122:
123: }
|