001: /*
002: License $Id: AbstractTag.java,v 1.7 2003/10/14 00:27:22 hendriks73 Exp $
003:
004: Copyright (c) 2001-2005 tagtraum industries.
005:
006: LGPL
007: ====
008:
009: jo! is free software; you can redistribute it and/or
010: modify it under the terms of the GNU Lesser General Public
011: License as published by the Free Software Foundation; either
012: version 2.1 of the License, or (at your option) any later version.
013:
014: jo! is distributed in the hope that it will be useful,
015: but WITHOUT ANY WARRANTY; without even the implied warranty of
016: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: Lesser General Public License for more details.
018:
019: You should have received a copy of the GNU Lesser General Public
020: License along with this library; if not, write to the Free Software
021: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
022:
023: For LGPL see <http://www.fsf.org/copyleft/lesser.txt>
024:
025:
026: Sun license
027: ===========
028:
029: This release contains software by Sun Microsystems. Therefore
030: the following conditions have to be met, too. They apply to the
031: files
032:
033: - lib/mail.jar
034: - lib/activation.jar
035: - lib/jsse.jar
036: - lib/jcert.jar
037: - lib/jaxp.jar
038: - lib/crimson.jar
039: - lib/servlet.jar
040: - lib/jnet.jar
041: - lib/jaas.jar
042: - lib/jaasmod.jar
043:
044: contained in this release.
045:
046: a. Licensee may not modify the Java Platform
047: Interface (JPI, identified as classes contained within the javax
048: package or any subpackages of the javax package), by creating additional
049: classes within the JPI or otherwise causing the addition to or modification
050: of the classes in the JPI. In the event that Licensee creates any
051: Java-related API and distribute such API to others for applet or
052: application development, you must promptly publish broadly, an accurate
053: specification for such API for free use by all developers of Java-based
054: software.
055:
056: b. Software is confidential copyrighted information of Sun and
057: title to all copies is retained by Sun and/or its licensors. Licensee
058: shall not modify, decompile, disassemble, decrypt, extract, or otherwise
059: reverse engineer Software. Software may not be leased, assigned, or
060: sublicensed, in whole or in part. Software is not designed or intended
061: for use in on-line control of aircraft, air traffic, aircraft navigation
062: or aircraft communications; or in the design, construction, operation or
063: maintenance of any nuclear facility. Licensee warrants that it will not
064: use or redistribute the Software for such purposes.
065:
066: c. Software is provided "AS IS," without a warranty
067: of any kind. ALL EXPRESS OR IMPLIED REPRESENTATIONS AND WARRANTIES,
068: INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
069: PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
070:
071: d. This License is effective until terminated. Licensee may
072: terminate this License at any time by destroying all copies of Software.
073: This License will terminate immediately without notice from Sun if Licensee
074: fails to comply with any provision of this License. Upon such termination,
075: Licensee must destroy all copies of Software.
076:
077: e. Software, including technical data, is subject to U.S.
078: export control laws, including the U.S. Export Administration Act and its
079: associated regulations, and may be subject to export or import regulations
080: in other countries. Licensee agrees to comply strictly with all such
081: regulations and acknowledges that it has the responsibility to obtain
082: licenses to export, re-export, or import Software. Software may not be
083: downloaded, or otherwise exported or re-exported (i) into, or to a national
084: or resident of, Cuba, Iraq, Iran, North Korea, Libya, Sudan, Syria or any
085: country to which the U.S. has embargoed goods; or (ii) to anyone on the
086: U.S. Treasury Department's list of Specially Designated Nations or the U.S.
087: Commerce Department's Table of Denial Orders.
088:
089:
090: Feedback
091: ========
092:
093: We encourage your feedback and suggestions and want to use your feedback to
094: improve the Software. Send all such feedback to:
095: <feedback@tagtraum.com>
096:
097: For more information on tagtraum industries and jo!
098: please see <http://www.tagtraum.com/>.
099:
100:
101: */
102: package com.tagtraum.framework.markup;
103:
104: import java.io.IOException;
105: import java.io.PushbackReader;
106:
107: /**
108: * Abstract tag suitable for being extended. Features parsing of quoted ('',"")
109: * and commented (java style) sections.
110: *
111: * @author <a href="mailto:hs@tagtraum.com">Hendrik Schreiber</a>
112: * @version 1.1beta1 $Id: AbstractTag.java,v 1.7 2003/10/14 00:27:22 hendriks73 Exp $
113: */
114: public class AbstractTag extends Tag {
115:
116: /**
117: * Source-Version
118: */
119: public static String vcid = "$Id: AbstractTag.java,v 1.7 2003/10/14 00:27:22 hendriks73 Exp $";
120:
121: public static final int NO_COMMENT = 0;
122: public static final int C_COMMENT = 1;
123: public static final int CPP_COMMENT = 2;
124: private boolean enableCComments = true;
125: private boolean enableCPPComments = true;
126: private boolean enableSingleQuotes = true;
127: private boolean enableDoubleQuotes = true;
128:
129: /**
130: * Constructor.
131: */
132: public AbstractTag(String aTagStart) {
133: super (aTagStart);
134: }
135:
136: public boolean isEnableSingleQuotes() {
137: return enableSingleQuotes;
138: }
139:
140: public void setEnableSingleQuotes(boolean enableSingleQuotes) {
141: this .enableSingleQuotes = enableSingleQuotes;
142: }
143:
144: public boolean isEnableDoubleQuotes() {
145: return enableDoubleQuotes;
146: }
147:
148: public void setEnableDoubleQuotes(boolean enableDoubleQuotes) {
149: this .enableDoubleQuotes = enableDoubleQuotes;
150: }
151:
152: public boolean isEnableCComments() {
153: return enableCComments;
154: }
155:
156: public void setEnableCComments(boolean enableCComments) {
157: this .enableCComments = enableCComments;
158: }
159:
160: public boolean isEnableCPPComments() {
161: return enableCPPComments;
162: }
163:
164: public void setEnableCPPComments(boolean enableCPPComments) {
165: this .enableCPPComments = enableCPPComments;
166: }
167:
168: /**
169: * Parses this element.
170: */
171: public void parse(PushbackReader aReader) throws IOException {
172: int c = 0;
173: boolean endOfTag = false;
174: int ringHead = 0;
175: int len = 0;
176: int bufpos;
177: int tagpos;
178: String theTagEnd = getTagEnd() + ">";
179: int theTagEndLength = theTagEnd.length();
180: char buf[] = new char[theTagEndLength];
181: int quoteChar = 0;
182: int lastChar = 0;
183: int comment = NO_COMMENT;
184: boolean escaped = false;
185:
186: // WORKAROUND: PushbackReader doesn't support skip properly
187: // for (int i=0; i<getTagStart().length(); i++) aReader.read();
188:
189: while (!endOfTag) {
190: c = aReader.read();
191: if (c == -1) {
192: if (quoteChar != 0) {
193: throw new ParserException(
194: "Missing closing quotation "
195: + (char) quoteChar + " in <"
196: + sb.toString());
197: }
198: if (comment == CPP_COMMENT) {
199: throw new ParserException(
200: "Missing closing comment '*/' in <"
201: + sb.toString());
202: }
203: // EOF
204: throw new ParserException(
205: "Tag wasn't properly closed before end of file: <"
206: + sb.toString());
207: //return; // EOF
208: }
209: append((char) c);
210: len++;
211: if (quoteChar == 0) {
212: if (lastChar == '/' && c == '/' && enableCComments) {
213: comment = C_COMMENT;
214: }
215: if (lastChar == '/' && c == '*' && enableCPPComments) {
216: comment = CPP_COMMENT;
217: }
218: }
219: if (enableDoubleQuotes && c == '\"' && !escaped
220: && comment == NO_COMMENT) {
221: quoteChar = setQuoteChar(quoteChar, c);
222: } else if (enableSingleQuotes && c == '\'' && !escaped
223: && comment == NO_COMMENT) {
224: quoteChar = setQuoteChar(quoteChar, c);
225: }
226:
227: buf[ringHead] = (char) c; // ringbuffer
228: if (len >= theTagEndLength && quoteChar == 0
229: && comment == NO_COMMENT) {
230: // compare, beginning from the last position backward
231: for (bufpos = ringHead + buf.length, tagpos = theTagEndLength - 1; tagpos >= 0; --bufpos, --tagpos) {
232: if (theTagEnd.charAt(tagpos) != buf[bufpos
233: % buf.length]) {
234: break;
235: }
236: }
237:
238: endOfTag = (tagpos == -1);
239: }
240:
241: if (quoteChar == 0) {
242: if ((lastChar == '*' && c == '/' && comment == CPP_COMMENT)
243: || (c == '\n' && comment == C_COMMENT)) {
244: comment = NO_COMMENT;
245: }
246: }
247:
248: ringHead = (++ringHead) % buf.length;
249: escaped = c == '\\' && !escaped;
250: lastChar = c;
251: }
252: finish();
253: }
254:
255: private int setQuoteChar(int quoteChar, int c) {
256: if (quoteChar == 0) {
257: quoteChar = c;
258: } else if (quoteChar == c) {
259: quoteChar = 0;
260: }
261: return quoteChar;
262: }
263:
264: protected void finish() {
265: myData = sb
266: .substring(0, sb.length() - getTagEnd().length() - 1);
267: }
268:
269: public String toString() {
270: return "<" + myData + getTagEnd() + ">";
271: }
272:
273: }
|