001    package org.codehaus.groovy.sandbox.markup;
002    /*
003    
004    Copyright 2004 (C) John Wilson. All Rights Reserved.
005    
006    Redistribution and use of this software and associated documentation
007    ("Software"), with or without modification, are permitted provided
008    that the following conditions are met:
009    
010    1. Redistributions of source code must retain copyright
011       statements and notices.  Redistributions must also contain a
012       copy of this document.
013    
014    2. Redistributions in binary form must reproduce the
015       above copyright notice, this list of conditions and the
016       following disclaimer in the documentation and/or other
017       materials provided with the distribution.
018    
019    3. The name "groovy" must not be used to endorse or promote
020       products derived from this Software without prior written
021       permission of The Codehaus.  For written permission,
022       please contact info@codehaus.org.
023    
024    4. Products derived from this Software may not be called "groovy"
025       nor may "groovy" appear in their names without prior written
026       permission of The Codehaus. "groovy" is a registered
027       trademark of The Codehaus.
028    
029    5. Due credit should be given to The Codehaus -
030       http://groovy.codehaus.org/
031    
032    THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
033    ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
034    NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
035    FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
036    THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
037    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
038    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
039    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
040    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
041    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
042    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
043    OF THE POSSIBILITY OF SUCH DAMAGE.
044    
045    */
046    
047    import java.io.IOException;
048    import java.io.Writer;
049    
050    public class StreamingMarkupWriter extends Writer {
051            protected final Writer delegate;
052            private final int encodingLimit = 127; // initally encode everything that's not US ASCII
053            private final Writer bodyWriter =  new Writer() {
054                                                                                            /* (non-Javadoc)
055                                                                                             * @see java.io.Writer#close()
056                                                                                             */
057                                                                                            public void close() throws IOException {
058                                                                                                    StreamingMarkupWriter.this.close();
059                                                                                            }
060                                                                                            
061                                                                                            /* (non-Javadoc)
062                                                                                             * @see java.io.Writer#flush()
063                                                                                             */
064                                                                                            public void flush() throws IOException {
065                                                                                                    StreamingMarkupWriter.this.flush();
066                                                                                            }
067                    
068                                                                                            /* (non-Javadoc)
069                                                                                             * @see java.io.Writer#write(int)
070                                                                                             */
071                                                                                            public void write(int c) throws IOException {
072                                                                                                    if (c > StreamingMarkupWriter.this.encodingLimit) {
073                                                                                                            StreamingMarkupWriter.this.delegate.write("&#x");
074                                                                                                            StreamingMarkupWriter.this.delegate.write(Integer.toHexString(c));
075                                                                                                            StreamingMarkupWriter.this.delegate.write(';');
076                                                                                                    } else if (c == '<') {
077                                                                                                            StreamingMarkupWriter.this.delegate.write("<");
078                                                                                                    } else if (c == '>') {
079                                                                                                            StreamingMarkupWriter.this.delegate.write(">");
080                                                                                                    } else if (c == '&') {
081                                                                                                            StreamingMarkupWriter.this.delegate.write("&");
082                                                                                                    } else {
083                                                                                                            StreamingMarkupWriter.this.delegate.write(c);
084                                                                                                    }
085                                                                                            }
086                                                                                            
087                                                                                            /* (non-Javadoc)
088                                                                                             * @see java.io.Writer#write(char[], int, int)
089                                                                                             */
090                                                                                            public void write(final char[] cbuf, int off, int len) throws IOException {
091                                                                                                    while (len-- > 0){
092                                                                                                            write(cbuf[off++]);
093                                                                                                    }
094                                                                                            }
095                                                                                            
096                                                                                            public Writer attributeValue() {
097                                                                                                    return StreamingMarkupWriter.this.attributeWriter;
098                                                                                            }
099                                                                                            
100                                                                                            public Writer bodyText() {
101                                                                                                    return bodyWriter;
102                                                                                            }
103                                                                                            
104                                                                                            public Writer unescaped() {
105                                                                                                    return StreamingMarkupWriter.this;
106                                                                                            }
107                                                                                    };
108            
109            private final Writer attributeWriter =  new Writer() {
110                                                                                                    /* (non-Javadoc)
111                                                                                                     * @see java.io.Writer#close()
112                                                                                                     */
113                                                                                                    public void close() throws IOException {
114                                                                                                            StreamingMarkupWriter.this.close();
115                                                                                                    }
116                                                                                    
117                                                                                                    /* (non-Javadoc)
118                                                                                                     * @see java.io.Writer#flush()
119                                                                                                     */
120                                                                                                    public void flush() throws IOException {
121                                                                                                            StreamingMarkupWriter.this.flush();
122                                                                                                    }
123                    
124                                                                                                    /* (non-Javadoc)
125                                                                                                     * @see java.io.Writer#write(int)
126                                                                                                     */
127                                                                                                    public void write(int c) throws IOException {
128                                                                                                            if (c == '\'') {
129                                                                                                                    StreamingMarkupWriter.this.delegate.write("'");
130                                                                                                            } else {
131                                                                                                                    StreamingMarkupWriter.this.bodyWriter.write(c);
132                                                                                                            }
133                                                                                                    }
134                                                                                                    
135                                                                                                    /* (non-Javadoc)
136                                                                                                     * @see java.io.Writer#write(char[], int, int)
137                                                                                                     */
138                                                                                                    public void write(final char[] cbuf, int off, int len) throws IOException {
139                                                                                                            while (len-- > 0){
140                                                                                                                    write(cbuf[off++]);
141                                                                                                            }
142                                                                                                    }
143                                                                                                    
144                                                                                                    public Writer attributeValue() {
145                                                                                                            return attributeWriter;
146                                                                                                    }
147                                                                                                    
148                                                                                                    public Writer bodyText() {
149                                                                                                            return StreamingMarkupWriter.this.bodyWriter;
150                                                                                                    }
151                                                                                                    
152                                                                                                    public Writer unescaped() {
153                                                                                                            return StreamingMarkupWriter.this;
154                                                                                                    }
155                                                                                            };
156    
157                    public StreamingMarkupWriter(final Writer delegate) {
158                            this.delegate = delegate;
159                    }
160            
161                    /* (non-Javadoc)
162                     * @see java.io.Writer#close()
163                     */
164                    public void close() throws IOException {
165                            this.delegate.close();
166                    }
167    
168                    /* (non-Javadoc)
169                     * @see java.io.Writer#flush()
170                     */
171                    public void flush() throws IOException {
172                            this.delegate.flush();
173                    }
174                    
175                    /* (non-Javadoc)
176                     * @see java.io.Writer#write(char[], int, int)
177                     */
178                    public void write(final char[] cbuf, int off, int len) throws IOException {
179                            this.delegate.write(cbuf, off, len);
180                    }
181                    
182                    public Writer attributeValue() {
183                            return this.attributeWriter;
184                    }
185                    
186                    public Writer bodyText() {
187                            return this.bodyWriter;
188                    }
189                    
190                    public Writer unescaped() {
191                            return this;
192                    }
193            }