001    package groovy.xml.streamingmarkupsupport;
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.OutputStreamWriter;
049    import java.io.Writer;
050    import java.nio.charset.Charset;
051    import java.nio.charset.CharsetEncoder;
052    
053    public class StreamingMarkupWriter extends Writer {
054            protected final Writer writer;
055      protected final String encoding;
056      protected final CharsetEncoder encoder;
057            private final Writer bodyWriter =  new Writer() {
058                                                                                            /* (non-Javadoc)
059                                                                                             * @see java.io.Writer#close()
060                                                                                             */
061                                                                                            public void close() throws IOException {
062                                                                                                    StreamingMarkupWriter.this.close();
063                                                                                            }
064                                                                                            
065                                                                                            /* (non-Javadoc)
066                                                                                             * @see java.io.Writer#flush()
067                                                                                             */
068                                                                                            public void flush() throws IOException {
069                                                                                                    StreamingMarkupWriter.this.flush();
070                                                                                            }
071                    
072                                                                                            /* (non-Javadoc)
073                                                                                             * @see java.io.Writer#write(int)
074                                                                                             */
075                                                                                            public void write(final int c) throws IOException {
076                                                                                                    if (!StreamingMarkupWriter.this.encoder.canEncode((char)c)) {
077                                                                                                            StreamingMarkupWriter.this.writer.write("&#x");
078                                                                                                            StreamingMarkupWriter.this.writer.write(Integer.toHexString(c));
079                                                                                                            StreamingMarkupWriter.this.writer.write(';');
080                                                                                                    } else if (c == '<') {
081                                                                                                            StreamingMarkupWriter.this.writer.write("&lt;");
082                                                                                                    } else if (c == '>') {
083                                                                                                            StreamingMarkupWriter.this.writer.write("&gt;");
084                                                                                                    } else if (c == '&') {
085                                                                                                            StreamingMarkupWriter.this.writer.write("&amp;");
086                                                                                                    } else {
087                                                                                                            StreamingMarkupWriter.this.writer.write(c);
088                                                                                                    }
089                                                                                            }
090                                                                                            
091                                                                                            /* (non-Javadoc)
092                                                                                             * @see java.io.Writer#write(char[], int, int)
093                                                                                             */
094                                                                                            public void write(final char[] cbuf, int off, int len) throws IOException {
095                                                                                                    while (len-- > 0){
096                                                                                                            write(cbuf[off++]);
097                                                                                                    }
098                                                                                            }
099                                                                                            
100                                                                                            public Writer attributeValue() {
101                                                                                                    return StreamingMarkupWriter.this.attributeWriter;
102                                                                                            }
103                                                                                            
104                                                                                            public Writer bodyText() {
105                                                                                                    return bodyWriter;
106                                                                                            }
107                                                                                            
108                                                                                            public Writer unescaped() {
109                                                                                                    return StreamingMarkupWriter.this;
110                                                                                            }
111                                                                                    };
112            
113            private final Writer attributeWriter =  new Writer() {
114                                                                                                    /* (non-Javadoc)
115                                                                                                     * @see java.io.Writer#close()
116                                                                                                     */
117                                                                                                    public void close() throws IOException {
118                                                                                                            StreamingMarkupWriter.this.close();
119                                                                                                    }
120                                                                                    
121                                                                                                    /* (non-Javadoc)
122                                                                                                     * @see java.io.Writer#flush()
123                                                                                                     */
124                                                                                                    public void flush() throws IOException {
125                                                                                                            StreamingMarkupWriter.this.flush();
126                                                                                                    }
127                    
128                                                                                                    /* (non-Javadoc)
129                                                                                                     * @see java.io.Writer#write(int)
130                                                                                                     */
131                                                                                                    public void write(final int c) throws IOException {
132                                                                                                            if (c == '\'') {
133                                                                                                                    StreamingMarkupWriter.this.writer.write("&apos;");
134                                                                                                            } else {
135                                                                                                                    StreamingMarkupWriter.this.bodyWriter.write(c);
136                                                                                                            }
137                                                                                                    }
138                                                                                                    
139                                                                                                    /* (non-Javadoc)
140                                                                                                     * @see java.io.Writer#write(char[], int, int)
141                                                                                                     */
142                                                                                                    public void write(final char[] cbuf, int off, int len) throws IOException {
143                                                                                                            while (len-- > 0){
144                                                                                                                    write(cbuf[off++]);
145                                                                                                            }
146                                                                                                    }
147                                                                                                    
148                                                                                                    public Writer attributeValue() {
149                                                                                                            return attributeWriter;
150                                                                                                    }
151                                                                                                    
152                                                                                                    public Writer bodyText() {
153                                                                                                            return StreamingMarkupWriter.this.bodyWriter;
154                                                                                                    }
155                                                                                                    
156                                                                                                    public Writer unescaped() {
157                                                                                                            return StreamingMarkupWriter.this;
158                                                                                                    }
159                                                                                            };
160    
161                    public StreamingMarkupWriter(final Writer writer, final String encoding) {
162                            this.writer = writer;
163          
164          if (encoding != null) {
165            this.encoding = encoding;
166          } else if (writer instanceof OutputStreamWriter) {
167            this.encoding = ((OutputStreamWriter)writer).getEncoding();
168          } else {
169            this.encoding = "US-ASCII";
170          }
171          
172          this.encoder = Charset.forName(this.encoding).newEncoder();
173                    }
174    
175        public StreamingMarkupWriter(final Writer writer) {
176          this(writer, null);
177        }
178        
179                    /* (non-Javadoc)
180                     * @see java.io.Writer#close()
181                     */
182                    public void close() throws IOException {
183                            this.writer.close();
184                    }
185    
186                    /* (non-Javadoc)
187                     * @see java.io.Writer#flush()
188                     */
189                    public void flush() throws IOException {
190                            this.writer.flush();
191                    }
192                    
193                    /* (non-Javadoc)
194                     * @see java.io.Writer#write(char[], int, int)
195                     */
196                    public void write(final char[] cbuf, int off, int len) throws IOException {
197                            this.writer.write(cbuf, off, len);
198                    }
199                    
200                    public Writer attributeValue() {
201                            return this.attributeWriter;
202                    }
203                    
204                    public Writer bodyText() {
205                            return this.bodyWriter;
206                    }
207                    
208                    public Writer unescaped() {
209                            return this;
210                    }
211            }