Source code: renderkits/util/Util.java
1 /*
2 * The contents of this file are subject to the terms
3 * of the Common Development and Distribution License
4 * (the License). You may not use this file except in
5 * compliance with the License.
6 *
7 * You can obtain a copy of the License at
8 * https://javaserverfaces.dev.java.net/CDDL.html or
9 * legal/CDDLv1.0.txt.
10 * See the License for the specific language governing
11 * permission and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL
14 * Header Notice in each file and include the License file
15 * at legal/CDDLv1.0.txt.
16 * If applicable, add the following below the CDDL Header,
17 * with the fields enclosed by brackets [] replaced by
18 * your own identifying information:
19 * "Portions Copyrighted [year] [name of copyright owner]"
20 *
21 * [Name of File] [ver.__] [Date]
22 *
23 * Copyright 2005 Sun Microsystems Inc. All Rights Reserved
24 */
25
26 package renderkits.util;
27
28 import javax.faces.FactoryFinder;
29 import javax.faces.application.Application;
30 import javax.faces.application.ApplicationFactory;
31 import javax.faces.component.UIComponent;
32 import javax.faces.convert.Converter;
33
34 import java.io.IOException;
35 import java.io.UnsupportedEncodingException;
36 import java.io.Writer;
37 import java.util.logging.Logger;
38
39 public class Util extends Object {
40
41 //
42 // Private/Protected Constants
43 //
44 public static final String FACES_LOGGER = "javax.enterprise.resource.jsf.";
45 public static final String RENDERKIT_LOGGER = "renderkit";
46 public static final String TAGLIB_LOGGER = "taglib";
47
48
49 public static final String FACES_LOG_STRINGS =
50 "com.sun.faces.LogStrings";
51
52 // Log instance for this class
53 private static Logger logger;
54
55 static {
56 logger = getLogger(FACES_LOGGER);
57 }
58
59 public static Logger getLogger(String loggerName) {
60 return Logger.getLogger(loggerName, FACES_LOG_STRINGS);
61 }
62
63 /** Utility method for determining if a component is 'disabled' or 'readonly' */
64 public static boolean componentIsDisabledOnReadonly(UIComponent component) {
65 Object disabledOrReadonly = null;
66 boolean result = false;
67 if (null !=
68 (disabledOrReadonly = component.getAttributes().get("disabled"))) {
69 if (disabledOrReadonly instanceof String) {
70 result = ((String) disabledOrReadonly).equalsIgnoreCase("true");
71 } else {
72 result = disabledOrReadonly.equals(Boolean.TRUE);
73 }
74 }
75 if ((result == false) &&
76 null !=
77 (disabledOrReadonly = component.getAttributes().get("readonly"))) {
78 if (disabledOrReadonly instanceof String) {
79 result = ((String) disabledOrReadonly).equalsIgnoreCase("true");
80 } else {
81 result = disabledOrReadonly.equals(Boolean.TRUE);
82 }
83 }
84
85 return result;
86 }
87
88 public static Converter getConverterForClass(Class converterClass) {
89 if (converterClass == null) {
90 return null;
91 }
92 try {
93 ApplicationFactory aFactory =
94 (ApplicationFactory) FactoryFinder.getFactory(
95 FactoryFinder.APPLICATION_FACTORY);
96 Application application = aFactory.getApplication();
97 return (application.createConverter(converterClass));
98 } catch (Exception e) {
99 return (null);
100 }
101 }
102
103
104 //----------------------------------------------------------
105 // The following is used to verify encodings
106 //----------------------------------------------------------
107 //
108 static public void validateEncoding(String encoding)
109 throws UnsupportedEncodingException {
110 if (encoding != null) {
111 // Try creating a string off of the default encoding
112 new String(encodingTestBytes, encoding);
113 }
114 }
115
116 // Private array used simply to verify character encodings
117 static private final byte[] encodingTestBytes = new byte[]{(byte) 65};
118
119 /**
120 * Write a string attribute. Note that this code
121 * is duplicated below for character arrays - change both
122 * places if you make any changes!!!
123 */
124 static public void writeAttribute(Writer out,
125 char[] buff,
126 String text) throws IOException {
127 int buffLength = buff.length;
128 int buffIndex = 0;
129
130 int length = text.length();
131 for (int i = 0; i < length; i++) {
132 char ch = text.charAt(i);
133
134 // Tilde or less...
135 if (ch < 0xA0) {
136 // If "?" or over, no escaping is needed (this covers
137 // most of the Latin alphabet)
138 if (ch >= 0x3f) {
139 buffIndex = addToBuffer(out, buff, buffIndex,
140 buffLength, ch);
141 } else if (ch >= 0x27) { // If above "'"...
142 // If between "'" and ";", no escaping is needed
143 if (ch < 0x3c) {
144 buffIndex = addToBuffer(out, buff, buffIndex,
145 buffLength, ch);
146 // Note - "<" isn't escaped in attributes, as per
147 // HTML spec
148 } else if (ch == '>') {
149 buffIndex = flushBuffer(out, buff, buffIndex);
150
151 out.write(">");
152 } else {
153 buffIndex = addToBuffer(out, buff, buffIndex,
154 buffLength, ch);
155 }
156 } else {
157 if (ch == '&') {
158 buffIndex = flushBuffer(out, buff, buffIndex);
159
160 // HTML 4.0, section B.7.1: ampersands followed by
161 // an open brace don't get escaped
162 if ((i + 1 < length) && (text.charAt(i + 1) == '{')) {
163 out.write(ch);
164 } else {
165 out.write("&");
166 }
167 } else if (ch == '"') {
168 buffIndex = flushBuffer(out, buff, buffIndex);
169
170 out.write(""");
171 } else {
172 buffIndex = addToBuffer(out, buff, buffIndex,
173 buffLength, ch);
174 }
175 }
176 } else {
177 buffIndex = flushBuffer(out, buff, buffIndex);
178
179 // Double-byte characters to encode.
180 // PENDING: when outputting to an encoding that
181 // supports double-byte characters (UTF-8, for example),
182 // we should not be encoding
183 _writeDecRef(out, ch);
184 }
185 }
186
187 flushBuffer(out, buff, buffIndex);
188 }
189
190 static public void writeAttribute(Writer out,
191 char[] buffer,
192 char[] text) throws IOException {
193 writeAttribute(out, buffer, text, 0, text.length);
194 }
195
196 /**
197 * Write a character array attribute. Note that this code
198 * is duplicated above for string - change both places if you make
199 * any changes!!!
200 */
201 static public void writeAttribute(Writer out,
202 char[] buff,
203 char[] text,
204 int start,
205 int length) throws IOException {
206 int buffLength = buff.length;
207 int buffIndex = 0;
208
209 int end = start + length;
210 for (int i = start; i < end; i++) {
211 char ch = text[i];
212
213 // Tilde or less...
214 if (ch < 0xA0) {
215 // If "?" or over, no escaping is needed (this covers
216 // most of the Latin alphabet)
217 if (ch >= 0x3f) {
218 buffIndex = addToBuffer(out, buff, buffIndex,
219 buffLength, ch);
220 } else if (ch >= 0x27) { // If above "'"...
221 if (ch < 0x3c) {
222 // If between "'" and ";", no escaping is needed
223 buffIndex = addToBuffer(out, buff, buffIndex,
224 buffLength, ch);
225 // Note - "<" isn't escaped in attributes, as per HTML spec
226 } else if (ch == '>') {
227 buffIndex = flushBuffer(out, buff, buffIndex);
228
229 out.write(">");
230 } else {
231 buffIndex = addToBuffer(out, buff, buffIndex,
232 buffLength, ch);
233 }
234 } else {
235 if (ch == '&') {
236 buffIndex = flushBuffer(out, buff, buffIndex);
237
238 // HTML 4.0, section B.7.1: ampersands followed by
239 // an open brace don't get escaped
240 if ((i + 1 < end) && (text[i + 1] == '{')) {
241 out.write(ch);
242 } else {
243 out.write("&");
244 }
245 } else if (ch == '"') {
246 buffIndex = flushBuffer(out, buff, buffIndex);
247
248 out.write(""");
249 } else {
250 buffIndex = addToBuffer(out, buff, buffIndex,
251 buffLength, ch);
252 }
253 }
254 } else {
255 buffIndex = flushBuffer(out, buff, buffIndex);
256
257 // Double-byte characters to encode.
258 // PENDING: when outputting to an encoding that
259 // supports double-byte characters (UTF-8, for example),
260 // we should not be encoding
261 _writeDecRef(out, ch);
262 }
263 }
264
265 flushBuffer(out, buff, buffIndex);
266 }
267
268 //-------------------------------------------------
269 // The following methods include the handling of
270 // escape characters....
271 //-------------------------------------------------
272
273 static public void writeText(Writer out,
274 char[] buffer,
275 char[] text) throws IOException {
276 writeText(out, buffer, text, 0, text.length);
277 }
278
279
280 /**
281 * Write char array text. Note that this code is duplicated below
282 * for Strings - change both places if you make any changes!!!
283 */
284 static public void writeText(Writer out,
285 char[] buff,
286 char[] text,
287 int start,
288 int length) throws IOException {
289 int buffLength = buff.length;
290 int buffIndex = 0;
291
292 int end = start + length;
293 for (int i = start; i < end; i++) {
294 char ch = text[i];
295
296 // Tilde or less...
297 if (ch < 0xA0) {
298 // If "?" or over, no escaping is needed (this covers
299 // most of the Latin alphabet)
300 if (ch >= 0x3f) {
301 buffIndex = addToBuffer(out, buff, buffIndex,
302 buffLength, ch);
303 } else if (ch >= 0x27) { // If above "'"...
304 // If between "'" and ";", no escaping is needed
305 if (ch < 0x3c) {
306 buffIndex = addToBuffer(out, buff, buffIndex,
307 buffLength, ch);
308 } else if (ch == '<') {
309 buffIndex = flushBuffer(out, buff, buffIndex);
310
311 out.write("<");
312 } else if (ch == '>') {
313 buffIndex = flushBuffer(out, buff, buffIndex);
314
315 out.write(">");
316 } else {
317 buffIndex = addToBuffer(out, buff, buffIndex,
318 buffLength, ch);
319 }
320 } else {
321 if (ch == '&') {
322 buffIndex = flushBuffer(out, buff, buffIndex);
323
324 out.write("&");
325 } else {
326 buffIndex = addToBuffer(out, buff, buffIndex,
327 buffLength, ch);
328 }
329 }
330 } else {
331 // Double-byte characters to encode.
332 // PENDING: when outputting to an encoding that
333 // supports double-byte characters (UTF-8, for example),
334 // we should not be encoding
335 buffIndex = flushBuffer(out, buff, buffIndex);
336 _writeDecRef(out, ch);
337 }
338 }
339
340 flushBuffer(out, buff, buffIndex);
341 }
342
343
344 /**
345 * Write String text. Note that this code is duplicated above for
346 * character arrays - change both places if you make any changes!!!
347 */
348 static public void writeText(Writer out,
349 char[] buff,
350 String text) throws IOException {
351 int buffLength = buff.length;
352 int buffIndex = 0;
353
354 int length = text.length();
355
356 for (int i = 0; i < length; i++) {
357 char ch = text.charAt(i);
358
359 // Tilde or less...
360 if (ch < 0xA0) {
361 // If "?" or over, no escaping is needed (this covers
362 // most of the Latin alphabet)
363 if (ch >= 0x3f) {
364 buffIndex = addToBuffer(out, buff, buffIndex,
365 buffLength, ch);
366 } else if (ch >= 0x27) { // If above "'"...
367 // If between "'" and ";", no escaping is needed
368 if (ch < 0x3c) {
369 buffIndex = addToBuffer(out, buff, buffIndex,
370 buffLength, ch);
371 } else if (ch == '<') {
372 buffIndex = flushBuffer(out, buff, buffIndex);
373 out.write("<");
374 } else if (ch == '>') {
375 buffIndex = flushBuffer(out, buff, buffIndex);
376 out.write(">");
377 } else {
378 buffIndex = addToBuffer(out, buff, buffIndex,
379 buffLength, ch);
380 }
381 } else {
382 if (ch == '&') {
383 buffIndex = flushBuffer(out, buff, buffIndex);
384
385 out.write("&");
386 } else {
387 buffIndex = addToBuffer(out, buff, buffIndex,
388 buffLength, ch);
389 }
390 }
391 } else {
392 // Double-byte characters to encode.
393 // PENDING: when outputting to an encoding that
394 // supports double-byte characters (UTF-8, for example),
395 // we should not be encoding
396 buffIndex = flushBuffer(out, buff, buffIndex);
397 _writeDecRef(out, ch);
398 }
399 }
400
401 flushBuffer(out, buff, buffIndex);
402 }
403
404 /**
405 * Writes a character as a decimal escape. Hex escapes are smaller than
406 * the decimal version, but Netscape didn't support hex escapes until
407 * 4.7.4.
408 */
409 static private void _writeDecRef(Writer out, char ch) throws IOException {
410 if (ch == '\u20ac') {
411 out.write("€");
412 return;
413 }
414 out.write("&#");
415 // Formerly used String.valueOf(). This version tests out
416 // about 40% faster in a microbenchmark (and on systems where GC is
417 // going gonzo, it should be even better)
418 int i = (int) ch;
419 if (i > 10000) {
420 out.write('0' + (i / 10000));
421 i = i % 10000;
422 out.write('0' + (i / 1000));
423 i = i % 1000;
424 out.write('0' + (i / 100));
425 i = i % 100;
426 out.write('0' + (i / 10));
427 i = i % 10;
428 out.write('0' + i);
429 } else if (i > 1000) {
430 out.write('0' + (i / 1000));
431 i = i % 1000;
432 out.write('0' + (i / 100));
433 i = i % 100;
434 out.write('0' + (i / 10));
435 i = i % 10;
436 out.write('0' + i);
437 } else {
438 out.write('0' + (i / 100));
439 i = i % 100;
440 out.write('0' + (i / 10));
441 i = i % 10;
442 out.write('0' + i);
443 }
444
445 out.write(';');
446 }
447
448 /**
449 * Flush the contents of the buffer to the output stream
450 * and return the reset buffer index
451 */
452 private static int flushBuffer(Writer out,
453 char[] buffer,
454 int bufferIndex) throws IOException {
455 if (bufferIndex > 0) {
456 out.write(buffer, 0, bufferIndex);
457 }
458
459 return 0;
460 }
461
462 /**
463 * Add a character to the buffer, flushing the buffer if the buffer is
464 * full, and returning the new buffer index
465 */
466 private static int addToBuffer(Writer out,
467 char[] buffer,
468 int bufferIndex,
469 int bufferLength,
470 char ch) throws IOException {
471 if (bufferIndex >= bufferLength) {
472 out.write(buffer, 0, bufferIndex);
473 bufferIndex = 0;
474 }
475
476 buffer[bufferIndex] = ch;
477
478 return bufferIndex + 1;
479 }
480
481
482 }
483