View Javadoc

1   /*
2    * @(#) $Id: EntityRefEncoder.java,v 1.1.2.1 2005/01/18 07:20:43 otsuka Exp $
3    * $Revision: 1.1.2.1 $
4    * Copyright (c) 2000 Shin Kinoshita All Rights Reserved.
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   * <>&"を<>&"に
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  //  public void setCanonical(boolean canonical) {
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      public static String encode(String s) {
59          if (s == null) return "";
60  
61          StringWriter w = new StringWriter();
62          try {
63              EntityRefEncoder.INSTANCE.translate(new StringReader(s), w);
64          } catch (IOException e) {
65              throw new RuntimeException();
66          }
67          return w.toString();
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("&lt;"); break;
88                  case '>': buf.append("&gt;"); break;
89                  case '&': buf.append("&amp;"); break;
90                  case '"': buf.append("&quot;"); 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("&lt;"); break;
105             case '>': w.write("&gt;"); break;
106             case '&': w.write("&amp;"); break;
107             case '"': w.write("&quot;"); 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 }