Author: bruno Date: Mon Nov 22 06:16:31 2004 New Revision: 106182 Modified: cocoon/trunk/src/java/org/apache/cocoon/i18n/XMLResourceBundle.java cocoon/trunk/src/java/org/apache/cocoon/xml/ParamSaxBuffer.java Log: Concerning {..} params spanning multiple character events: replaced my earlier post-processing solution with an altered version of the one provided by bugzilla 31887 (by Neil Bacon).
Modified: cocoon/trunk/src/java/org/apache/cocoon/i18n/XMLResourceBundle.java Url: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/i18n/XMLResourceBundle.java?view=diff&rev=106182&p1=cocoon/trunk/src/java/org/apache/cocoon/i18n/XMLResourceBundle.java&r1=106181&p2=cocoon/trunk/src/java/org/apache/cocoon/i18n/XMLResourceBundle.java&r2=106182 ============================================================================== --- cocoon/trunk/src/java/org/apache/cocoon/i18n/XMLResourceBundle.java (original) +++ cocoon/trunk/src/java/org/apache/cocoon/i18n/XMLResourceBundle.java Mon Nov 22 06:16:31 2004 @@ -198,7 +198,6 @@ case 2: if (this.namespace.equals(ns) && EL_MESSAGE.equals(localName)) { // </i18n:message> - this.buffer.processParams(); this.buffer = null; state --; } else { Modified: cocoon/trunk/src/java/org/apache/cocoon/xml/ParamSaxBuffer.java Url: http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/xml/ParamSaxBuffer.java?view=diff&rev=106182&p1=cocoon/trunk/src/java/org/apache/cocoon/xml/ParamSaxBuffer.java&r1=106181&p2=cocoon/trunk/src/java/org/apache/cocoon/xml/ParamSaxBuffer.java&r2=106182 ============================================================================== --- cocoon/trunk/src/java/org/apache/cocoon/xml/ParamSaxBuffer.java (original) +++ cocoon/trunk/src/java/org/apache/cocoon/xml/ParamSaxBuffer.java Mon Nov 22 06:16:31 2004 @@ -17,29 +17,33 @@ import java.util.Iterator; import java.util.Map; -import java.util.List; -import java.util.ArrayList; import java.io.Writer; import java.io.IOException; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; +import org.xml.sax.Attributes; /** * Modification of the SAX buffer with parameterization capabilities. * - * <p>Any <code>{name}</code> expression inside of the character events can be + * Any <code>{name}</code> expression inside of the character events can be * replaced by the content of another SaxBuffer if it is present in the map * passed to the [EMAIL PROTECTED] #toSAX(ContentHandler, Map)} method. * - * <p>Once all events have been pushed into this buffer, you need to call - * [EMAIL PROTECTED] #processParams()}.</p> - * * @author <a href="mailto:[EMAIL PROTECTED]">Vadim Gritsenko</a> * @version CVS $Id$ */ public class ParamSaxBuffer extends SaxBuffer { + /** + * If ch (in characters()) contains an unmatched '{' then + * we save the chars from '{' onward in previous_ch. + * Next call to characters() prepends the saved chars to ch before processing + * (and sets previous_ch to null). + */ + private char[] previous_ch = null; + /** * Creates empty SaxBuffer */ @@ -54,102 +58,113 @@ } /** - * Parses text in character events and extracts <code>{name}</code> parameters for later + * Parses text and extracts <code>{name}</code> parameters for later * substitution. */ - public void processParams() throws SAXException { - // what we do here is running over all sax bits and copying them over - // into a new list, and meanwhile processing all Character bits - - int initialSize; - if (saxbits.size() <= 3) - initialSize = 6; - else - initialSize = (int)((double)saxbits.size() * 1.35d); - - List newSaxBits = new ArrayList(initialSize); - - int i = 0; - while (i < saxbits.size()) { - Object bit = saxbits.get(i); - if (bit instanceof Characters) { - char[] chars = ((Characters)bit).ch; - - // check if there are more character events immediately following this one, - // if so merge all data into one big array - int consecutiveCharacterEventCount = 0; - int totalLength = chars.length; - for (int k = i + 1; k < saxbits.size(); k++) { - Object otherbit = saxbits.get(k); - if (otherbit instanceof Characters) { - consecutiveCharacterEventCount++; - totalLength += ((Characters)otherbit).ch.length; - } else { - break; - } - } + public void characters(char ch[], int start, int length) throws SAXException { - if (consecutiveCharacterEventCount > 0) { - char[] newchars = new char[totalLength]; - System.arraycopy(chars, 0, newchars, 0, chars.length); - int newCharPos = chars.length; - for (int k = 0; k < consecutiveCharacterEventCount; k++) { - Object otherbit = saxbits.get(i + 1 + k); - char[] otherchars = ((Characters)otherbit).ch; - System.arraycopy(otherchars, 0, newchars, newCharPos, otherchars.length); - newCharPos += otherchars.length; - } - chars = newchars; - i += consecutiveCharacterEventCount + 1; - } else { - i++; + if (previous_ch != null) { + // prepend char's from previous_ch to ch + char[] buf = new char[length + previous_ch.length]; + System.arraycopy(previous_ch, 0, buf, 0, previous_ch.length); + System.arraycopy(ch, start, buf, previous_ch.length, length); + ch = buf; + start = 0; + length += previous_ch.length; + previous_ch = null; + } + + final int end = start + length; + for (int i = start; i < end; i++) { + if (ch[i] == '{') { + // Send any collected characters so far + if (i > start) { + addBit(new Characters(ch, start, i - start)); } - // now process the actual {...} - int start = 0; - final int end = chars.length; - for (int r = 0; r < end; r++) { - if (chars[r] == '{') { - // Send any collected characters so far - if (r > start) { - newSaxBits.add(new Characters(chars, start, r - start)); - } - - // Find closing brace, and construct parameter name - StringBuffer name = new StringBuffer(); - int j = r + 1; - for (; j < end; j++) { - if (chars[j] == '}') { - break; - } - name.append(chars[j]); - } - if (j == end) { - throw new SAXException("Unclosed '}'"); - } - newSaxBits.add(new Parameter(name.toString())); - - // Continue processing - r = j; - start = j + 1; - continue; + // Find closing brace, and construct parameter name + StringBuffer name = new StringBuffer(); + int j = i + 1; + for (; j < end; j++) { + if (ch[j] == '}') { + break; } + name.append(ch[j]); } - - // Send any tailing characters - if (start < end) { - newSaxBits.add(new Characters(chars, start, end - start)); + if (j == end) { + // '{' without a closing '}' + // save char's from '{' in previous_ch in case the following call to characters() + // provides the '}' + previous_ch = new char[end - i]; + System.arraycopy(ch, i, previous_ch, 0, end - i); + break; } - } else { - newSaxBits.add(bit); - i++; + addBit(new Parameter(name.toString())); + + // Continue processing + i = j; + start = j + 1; + continue; } } - this.saxbits = newSaxBits; + + // Send any tailing characters + if (start < end) { + addBit(new Characters(ch, start, end - start)); + } } - public void characters(char ch[], int start, int length) throws SAXException { - addBit(new Characters(ch, start, length)); + public void endElement(String namespaceURI, String localName, String qName) throws SAXException { + flushChars(); + super.endElement(namespaceURI, localName, qName); + } + + public void ignorableWhitespace(char ch[], int start, int length) throws SAXException { + flushChars(); + super.ignorableWhitespace(ch, start, length); + } + + public void processingInstruction(String target, String data) throws SAXException { + flushChars(); + super.processingInstruction(target, data); + } + + public void startDocument() throws SAXException { + flushChars(); + super.startDocument(); + } + + public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { + flushChars(); + super.startElement(namespaceURI, localName, qName, atts); + } + + public void endDocument() throws SAXException { + flushChars(); + super.endDocument(); + } + + public void comment(char ch[], int start, int length) throws SAXException { + flushChars(); + super.comment(ch, start, length); + } + + public void endDTD() throws SAXException { + flushChars(); + super.endDTD(); + } + + public void startDTD(String name, String publicId, String systemId) throws SAXException { + flushChars(); + super.startDTD(name, publicId, systemId); + } + + private void flushChars() { + // Handle saved chars (in case we had a '{' with no matching '}'). + if (previous_ch != null) { + addBit(new Characters(previous_ch, 0, previous_ch.length)); + previous_ch = null; + } } /**