View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.tobago.internal.util;
21  
22  import java.io.IOException;
23  import java.io.Writer;
24  
25  public abstract class WriterUtils {
26    protected static final char[] EMPTY = new char[0];
27    //
28    // Entities from HTML 4.0, section 24.2.1; character codes 0xA0 to 0xFF
29    //
30    protected static final char[][] ISO8859_1_ENTITIES = new char[][]{
31        "nbsp".toCharArray(),
32        "iexcl".toCharArray(),
33        "cent".toCharArray(),
34        "pound".toCharArray(),
35        "curren".toCharArray(),
36        "yen".toCharArray(),
37        "brvbar".toCharArray(),
38        "sect".toCharArray(),
39        "uml".toCharArray(),
40        "copy".toCharArray(),
41        "ordf".toCharArray(),
42        "laquo".toCharArray(),
43        "not".toCharArray(),
44        "shy".toCharArray(),
45        "reg".toCharArray(),
46        "macr".toCharArray(),
47        "deg".toCharArray(),
48        "plusmn".toCharArray(),
49        "sup2".toCharArray(),
50        "sup3".toCharArray(),
51        "acute".toCharArray(),
52        "micro".toCharArray(),
53        "para".toCharArray(),
54        "middot".toCharArray(),
55        "cedil".toCharArray(),
56        "sup1".toCharArray(),
57        "ordm".toCharArray(),
58        "raquo".toCharArray(),
59        "frac14".toCharArray(),
60        "frac12".toCharArray(),
61        "frac34".toCharArray(),
62        "iquest".toCharArray(),
63        "Agrave".toCharArray(),
64        "Aacute".toCharArray(),
65        "Acirc".toCharArray(),
66        "Atilde".toCharArray(),
67        "Auml".toCharArray(),
68        "Aring".toCharArray(),
69        "AElig".toCharArray(),
70        "Ccedil".toCharArray(),
71        "Egrave".toCharArray(),
72        "Eacute".toCharArray(),
73        "Ecirc".toCharArray(),
74        "Euml".toCharArray(),
75        "Igrave".toCharArray(),
76        "Iacute".toCharArray(),
77        "Icirc".toCharArray(),
78        "Iuml".toCharArray(),
79        "ETH".toCharArray(),
80        "Ntilde".toCharArray(),
81        "Ograve".toCharArray(),
82        "Oacute".toCharArray(),
83        "Ocirc".toCharArray(),
84        "Otilde".toCharArray(),
85        "Ouml".toCharArray(),
86        "times".toCharArray(),
87        "Oslash".toCharArray(),
88        "Ugrave".toCharArray(),
89        "Uacute".toCharArray(),
90        "Ucirc".toCharArray(),
91        "Uuml".toCharArray(),
92        "Yacute".toCharArray(),
93        "THORN".toCharArray(),
94        "szlig".toCharArray(),
95        "agrave".toCharArray(),
96        "aacute".toCharArray(),
97        "acirc".toCharArray(),
98        "atilde".toCharArray(),
99        "auml".toCharArray(),
100       "aring".toCharArray(),
101       "aelig".toCharArray(),
102       "ccedil".toCharArray(),
103       "egrave".toCharArray(),
104       "eacute".toCharArray(),
105       "ecirc".toCharArray(),
106       "euml".toCharArray(),
107       "igrave".toCharArray(),
108       "iacute".toCharArray(),
109       "icirc".toCharArray(),
110       "iuml".toCharArray(),
111       "eth".toCharArray(),
112       "ntilde".toCharArray(),
113       "ograve".toCharArray(),
114       "oacute".toCharArray(),
115       "ocirc".toCharArray(),
116       "otilde".toCharArray(),
117       "ouml".toCharArray(),
118       "divide".toCharArray(),
119       "oslash".toCharArray(),
120       "ugrave".toCharArray(),
121       "uacute".toCharArray(),
122       "ucirc".toCharArray(),
123       "uuml".toCharArray(),
124       "yacute".toCharArray(),
125       "thorn".toCharArray(),
126       "yuml".toCharArray()
127   };
128   private final Writer out;
129   private final ResponseWriterBuffer buffer;
130   private final boolean utf8;
131 
132   public WriterUtils(final Writer out, final String characterEncoding) {
133     this.out = out;
134     buffer = new ResponseWriterBuffer(out);
135     utf8 = "utf-8".equalsIgnoreCase(characterEncoding);
136   }
137 
138   public void writeAttributeValue(final String text)
139       throws IOException {
140     writeEncodedValue(text.toCharArray(), 0, text.length(), true);
141   }
142 
143   public void writeText(final String text) throws IOException {
144     writeEncodedValue(text.toCharArray(), 0, text.length(), false);
145   }
146 
147   public void writeText(final char[] text, final int start, final int length)
148       throws IOException {
149     writeEncodedValue(text, start, length, false);
150   }
151 
152   protected abstract void writeEncodedValue(char[] text, int start,
153                                             int length, boolean isAttribute)
154       throws IOException;
155 
156   /**
157    * Writes a character as a decimal escape.  Hex escapes are smaller than
158    * the decimal version, but Netscape didn't support hex escapes until
159    * 4.7.4.
160    */
161   protected void writeDecRef(final char ch) throws IOException {
162     if (ch == '\u20ac') {
163       out.write("€");
164       return;
165     }
166     out.write("&#");
167     // Formerly used String.valueOf().  This version tests out
168     // about 40% faster in a microbenchmark (and on systems where GC is
169     // going gonzo, it should be even better)
170     int i = (int) ch;
171     if (i > 10000) {
172       out.write('0' + (i / 10000));
173       i = i % 10000;
174       out.write('0' + (i / 1000));
175       i = i % 1000;
176       out.write('0' + (i / 100));
177       i = i % 100;
178       out.write('0' + (i / 10));
179       i = i % 10;
180       out.write('0' + i);
181     } else if (i > 1000) {
182       out.write('0' + (i / 1000));
183       i = i % 1000;
184       out.write('0' + (i / 100));
185       i = i % 100;
186       out.write('0' + (i / 10));
187       i = i % 10;
188       out.write('0' + i);
189     } else {
190       out.write('0' + (i / 100));
191       i = i % 100;
192       out.write('0' + (i / 10));
193       i = i % 10;
194       out.write('0' + i);
195     }
196 
197     out.write(';');
198   }
199 
200   protected final Writer getOut() {
201     return out;
202   }
203 
204   protected final ResponseWriterBuffer getBuffer() {
205     return buffer;
206   }
207 
208   protected final boolean isUtf8() {
209     return utf8;
210   }
211 }