1
2
3
4
5
6
7 package com.ozacc.mail.fetch.impl.sk_jp.text;
8
9 import java.io.IOException;
10 import java.io.Reader;
11 import java.io.Writer;
12
13 /***
14 * <>&"を&lt;&gt;&amp;&quot;に
15 * 変換するTranslatorです。
16 * リエントラントなので、通常はINSTANCE/CANONICAL_INSTANCEを用いればよいです。
17 * またStringオブジェクトに対してはencode()メソッドが使用できます。
18 * @version $Revision: 1.1.2.1 $ $Date: 2005/01/18 07:20:43 $
19 * @author Shin
20 */
21 public class EntityRefEncoder implements Translator {
22 public static final EntityRefEncoder CANONICAL_INSTANCE =
23 new EntityRefEncoder(true);
24 public static final EntityRefEncoder INSTANCE =
25 new EntityRefEncoder(false);
26
27 public EntityRefEncoder() {
28 this(false);
29 }
30 public EntityRefEncoder(boolean canonical) {
31 setCanonical(canonical);
32 }
33
34 private boolean canonicalStatus;
35 private void setCanonical(boolean canonical) {
36
37 this.canonicalStatus = canonical;
38 }
39
40 /***
41 * 文字ストリームから入力した文字列を任意の変換を
42 * 行いながら出力ストリームに書き出します。
43 * <p>
44 * </p>
45 */
46 public void translate(Reader r, Writer w) throws IOException {
47 int c;
48 while ((c = r.read()) != -1) {
49 translate((char)c, w, canonicalStatus);
50 }
51 w.flush();
52 }
53
54 public String translate(String source) {
55 return encode(source);
56 }
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 /***
72 * 文字列の実体参照化を行います。
73 * @param s 対象文字列
74 * @return 変換後文字列
75 */
76
77 public static String encode(String s) {
78 if (s == null) return "";
79
80 int len = s.length();
81 StringBuffer buf = new StringBuffer(len + 128);
82 char c;
83
84 for (int i = 0; i < len; i++) {
85 c = s.charAt(i);
86 switch (c) {
87 case '<': buf.append("<"); break;
88 case '>': buf.append(">"); break;
89 case '&': buf.append("&"); break;
90 case '"': buf.append("""); break;
91 default:
92 buf.append(c);
93 }
94 }
95 return new String(buf);
96 }
97
98 /***
99 * 特定の文字を実体参照に変換して書き出します。
100 */
101 public static void translate(char c, Writer w, boolean canonical)
102 throws IOException {
103 switch (c) {
104 case '<': w.write("<"); break;
105 case '>': w.write(">"); break;
106 case '&': w.write("&"); break;
107 case '"': w.write("""); break;
108 case '\r':
109 case '\n':
110 if (canonical) {
111 w.write("&#");
112 w.write(Integer.toString(c));
113 w.write(';');
114 } else {
115 w.write(c);
116 }
117 break;
118 default:
119 w.write(c);
120 }
121 }
122
123 /***
124 * 実体参照変換されている文字列をもとに戻します。
125 * @param s 対象文字列
126 * @return 変換後文字列
127 */
128 public static String decode(String s) {
129 if (s == null) return "";
130
131 int len = s.length();
132 StringBuffer buf = new StringBuffer(len);
133 char c;
134
135 for (int i = 0; i < len; i++) {
136 c = s.charAt(i);
137 if (c != '&' || i > len - 4) {
138 buf.append(c);
139 continue;
140 }
141 if ((s.charAt(i + 2) == 't' || s.charAt(i + 2) == 'T') &&
142 s.charAt(i + 3) == ';') {
143 switch (s.charAt(i + 1)) {
144 case 'l':
145 case 'L':
146 buf.append('<');
147 i += 3;
148 continue;
149 case 'g':
150 case 'G':
151 buf.append('>');
152 i += 3;
153 continue;
154 }
155 } else if (i < len - 4 &&
156 (s.charAt(i + 1) == 'a' || s.charAt(i + 1) == 'A') &&
157 (s.charAt(i + 2) == 'm' || s.charAt(i + 2) == 'M') &&
158 (s.charAt(i + 3) == 'p' || s.charAt(i + 3) == 'P') &&
159 s.charAt(i + 4) == ';') {
160 buf.append('&');
161 i += 4;
162 continue;
163 } else if (i < len - 5 &&
164 (s.charAt(i + 1) == 'q' || s.charAt(i + 1) == 'Q') &&
165 (s.charAt(i + 2) == 'u' || s.charAt(i + 2) == 'U') &&
166 (s.charAt(i + 3) == 'o' || s.charAt(i + 3) == 'O') &&
167 (s.charAt(i + 4) == 't' || s.charAt(i + 4) == 'T') &&
168 s.charAt(i + 5) == ';') {
169 buf.append('"');
170 i += 5;
171 continue;
172 }
173 buf.append(c);
174 }
175 return new String(buf);
176 }
177 }