001: /*******************************************************************************
002: * Copyright (c) 2003 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jsp;
011:
012: import java.io.IOException;
013: import java.io.Reader;
014:
015: public abstract class AbstractJspParser {
016:
017: private Reader fReader;
018: private boolean fHasUnread;
019: private int fUnread;
020: private int fPos;
021: protected int fLines = 1;
022:
023: AbstractJspParser() {
024: super ();
025: }
026:
027: private int getc() throws IOException {
028: fPos++;
029: if (fHasUnread) {
030: fHasUnread = false;
031: return fUnread;
032: }
033:
034: int ch = fReader.read();
035:
036: if (ch == '\n') // LF
037: fLines++;
038: else if (ch == '\r') { // CR
039: int nextCh = getc();
040: if (nextCh != '\n')
041: fLines++;
042: return nextCh;
043: }
044: return ch;
045: }
046:
047: private void ungetc(int c) {
048: fHasUnread = true;
049: fUnread = c;
050: fPos--;
051: }
052:
053: private void parseDirective() throws IOException {
054: StringBuffer sb = new StringBuffer();
055: int pos = fPos;
056: while (true) {
057: int c = getc();
058: if (c == '%') {
059: c = getc();
060: if (c == '>') {
061: // get attributes
062: parseAttributes(pos, sb.toString());
063: return;
064: }
065: }
066: sb.append((char) c);
067: }
068: }
069:
070: private void parseTag(boolean endTag) throws IOException {
071: StringBuffer sb = new StringBuffer();
072: int pos = fPos;
073: while (true) {
074: int c = getc();
075: if (c == '/') {
076: c = getc();
077: if (c == '>') {
078: // get attributes
079: parseAttributes(pos, sb.toString());
080: return;
081: } else {
082: ungetc(c);
083: }
084: } else if (c == '>') {
085: // get attributes
086: parseAttributes(pos, sb.toString());
087: return;
088: }
089: sb.append((char) c);
090: }
091: }
092:
093: private void parseComment() throws IOException {
094: while (true) {
095: int c = getc();
096: if (c == '-') {
097: c = getc();
098: if (c == '-') {
099: c = getc();
100: if (c == '%') {
101: c = getc();
102: if (c == '>') {
103: return;
104: }
105: }
106: }
107: }
108: }
109: }
110:
111: private void parseJava(char type) throws IOException {
112: StringBuffer sb = new StringBuffer();
113: int line = fLines;
114: while (true) {
115: int c = getc();
116: if (c == '%') {
117: c = getc();
118: if (c == '>') {
119: java(type, sb.toString(), line);
120: return;
121: }
122: }
123: sb.append((char) c);
124: }
125: }
126:
127: protected void java(char tagType, String contents, int line) {
128: // empty implementation
129: }
130:
131: private void parseAttributes(int pos, String s) {
132:
133: boolean hasValue = false;
134: StringBuffer name = new StringBuffer();
135: StringBuffer value = new StringBuffer();
136: String startTag = ""; //$NON-NLS-1$
137: int i = 0;
138: int ix = 0;
139: int startName = 0;
140: int startValue = 0;
141: char c = s.charAt(i++);
142:
143: try {
144: while (true) {
145:
146: // whitespace
147: while (Character.isWhitespace(c))
148: c = s.charAt(i++);
149:
150: startName = i;
151: while (Character.isLetterOrDigit(c) || c == ':') {
152: name.append(c);
153: c = s.charAt(i++);
154: }
155:
156: // whitespace
157: while (Character.isWhitespace(c))
158: c = s.charAt(i++);
159:
160: hasValue = false;
161: if (c == '=') {
162: c = s.charAt(i++);
163:
164: // value
165: while (Character.isWhitespace(c))
166: c = s.charAt(i++);
167:
168: startValue = i;
169:
170: // Special handling for this taglib tag
171: if (startTag.equals("c:out")) { //$NON-NLS-1$
172: value = value.append(s.substring(startValue,
173: Math.max(startValue, s.length() - 2)));
174: name.setLength(0);
175: tagAttribute(name.toString(), value.toString(),
176: startName + pos, startValue + pos);
177: break;
178: } else if (c == '"') {
179: c = s.charAt(i++);
180: while (c != '"') {
181: value.append(c);
182: c = s.charAt(i++);
183: }
184: c = s.charAt(i++);
185:
186: } else {
187: while (Character.isLetterOrDigit(c)) {
188: value.append(c);
189: c = s.charAt(i++);
190: }
191: }
192: hasValue = true;
193: }
194:
195: if (ix == 0) {
196: startTag = name.toString();
197: startTag(false, startTag, startName + pos);
198: } else
199: tagAttribute(name.toString(), hasValue ? value
200: .toString() : null, startName + pos,
201: startValue + pos);
202: ix++;
203:
204: name.setLength(0);
205: value.setLength(0);
206: }
207: } catch (StringIndexOutOfBoundsException e) {
208: // we don't log this exception because it is used
209: // as one way to exit the scanning loop
210: }
211:
212: if (name.length() > 0) {
213: if (ix == 0)
214: startTag(false, name.toString(), startName + pos);
215: else
216: tagAttribute(name.toString(), hasValue ? value
217: .toString() : null, startName + pos, startValue
218: + pos);
219: }
220:
221: endTag(false);
222: }
223:
224: protected void startTag(boolean endTag, String name, int startName) {
225: // empty implementation
226: }
227:
228: protected void tagAttribute(String attrName, String value,
229: int startName, int startValue) {
230: // empty implementation
231: }
232:
233: protected void endTag(boolean end) {
234: // empty implementation
235: }
236:
237: protected void text(String t, int line) {
238: // empty implementation
239: }
240:
241: void parse(Reader reader) throws IOException {
242: int c;
243: StringBuffer buffer = new StringBuffer();
244: fPos = 0;
245: fLines = 1;
246: int line = fLines;
247: fReader = reader;
248:
249: while (true) {
250: c = getc();
251: switch (c) {
252: case -1:
253: if (buffer.length() > 0)
254: text(buffer.toString(), line);
255: return;
256: case '<':
257: c = getc();
258: if (c == '%') {
259: // flush buffer
260: if (buffer.length() > 0) {
261: text(buffer.toString(), line);
262: buffer.setLength(0);
263: line = fLines;
264: }
265: c = getc();
266: switch (c) {
267: case '-':
268: c = getc();
269: if (c == '-') {
270: parseComment();
271: } else {
272: ungetc(c);
273: continue;
274: }
275: break;
276: case '@':
277: parseDirective();
278: break;
279: case ' ':
280: case '!':
281: case '=':
282: parseJava((char) c);
283: break;
284: default:
285: parseComment();
286: break;
287: }
288: } else if (c == '/') {
289: parseTag(true);
290: } else {
291: ungetc(c);
292: parseTag(false);
293: }
294: break;
295: default:
296: buffer.append((char) c);
297: break;
298: }
299: }
300: }
301: }
|