1 /* This software is published under the terms of the OpenSymphony Software
2 * License version 1.1, of which a copy has been included with this
3 * distribution in the LICENSE.txt file. */
4 package com.opensymphony.module.sitemesh.filter;
5
6 import java.io.ByteArrayInputStream;
7 import java.io.CharArrayWriter;
8 import java.io.IOException;
9 import java.io.InputStreamReader;
10 import java.nio.ByteBuffer;
11 import java.nio.CharBuffer;
12 import java.nio.charset.Charset;
13 import java.nio.charset.CharsetDecoder;
14 import java.nio.charset.CoderResult;
15 import java.nio.charset.CodingErrorAction;
16
17 /**
18 * Converts text stored in byte[] to char[] using specified encoding.
19 *
20 * @author <a href="mailto:scott@atlassian.com">Scott Farquhar</a>
21 * @author <a href="mailto:hani@formicary.net">Hani Suleiman</a>
22 * @author Joe Walnes
23 * @version $Revision: 1.1 $
24 */
25 public class TextEncoder {
26
27 private static final String DEFAULT_ENCODING = System.getProperty("file.encoding");
28 private static final boolean JDK14 =
29 System.getProperty("java.version").startsWith("1.4")
30 || System.getProperty("java.version").startsWith("1.5");
31
32 public char[] encode(byte[] data, String encoding) throws IOException {
33 if (encoding == null) {
34 encoding = DEFAULT_ENCODING;
35 }
36 if (JDK14) {
37 return get14Buffer(data, encoding);
38 } else {
39 return get13Buffer(data, encoding);
40 }
41 }
42
43 private char[] get13Buffer(byte[] data, String encoding) throws IOException {
44 CharArrayWriter out = null;
45 // Why all this indirection? Because we are being given bytes, and we have to then write
46 // them to characters. We need to know the encoding of the characterset that we are creating.
47 // The test that verifies this is InlineDecoratorTest (inline/page6.jsp).
48 InputStreamReader reader;
49 out = new CharArrayWriter();
50 if (encoding != null) {
51 reader = new InputStreamReader(new ByteArrayInputStream(data), encoding);
52 } else {
53 reader = new InputStreamReader(new ByteArrayInputStream(data));
54 }
55
56 int i;
57 while ((i = reader.read()) != -1) {
58 out.write(i);
59 }
60 return out.toCharArray();
61 }
62
63 private char[] get14Buffer(byte[] data, String encoding) throws IOException {
64 if (!Charset.isSupported(encoding)) throw new IOException("Unsupported encoding " + encoding);
65 Charset charset = Charset.forName(encoding);
66 CharsetDecoder cd = charset.newDecoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE);
67 int en = (int) (cd.maxCharsPerByte() * data.length);
68 char[] ca = new char[en];
69 ByteBuffer bb = ByteBuffer.wrap(data);
70 CharBuffer cb = CharBuffer.wrap(ca);
71 CoderResult cr = cd.decode(bb, cb, true);
72 if (!cr.isUnderflow()) {
73 cr.throwException();
74 }
75 cr = cd.flush(cb);
76 if (!cr.isUnderflow()) {
77 cr.throwException();
78 }
79 return trim(ca, cb.position());
80 }
81
82 private char[] trim(char[] ca, int len) {
83 if (len == ca.length) {
84 return ca;
85 }
86 char[] tca = new char[len];
87 System.arraycopy(ca, 0, tca, 0, len);
88 return tca;
89 }
90
91 }