KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > server > host > DomainName


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  * Free SoftwareFoundation, Inc.
23  * 59 Temple Place, Suite 330
24  * Boston, MA 02111-1307 USA
25  *
26  * @author Scott Ferguson
27  */

28
29 package com.caucho.server.host;
30
31 import com.caucho.log.Log;
32 import com.caucho.util.CharBuffer;
33 import com.caucho.util.L10N;
34
35 import java.util.logging.Level JavaDoc;
36 import java.util.logging.Logger JavaDoc;
37
38
39 /**
40  * Domain name normalization
41  */

42 public class DomainName {
43   static final Logger JavaDoc log = Log.open(DomainName.class);
44   static final L10N L = new L10N(DomainName.class);
45
46   private final static char ENCODE[];
47   private final static int DECODE[];
48
49   private final static int base = 36;
50   private final static int tmin = 1;
51   private final static int tmax = 26;
52   private final static int skew = 38;
53   private final static int damp = 700;
54   private final static int initialBias = 72;
55   private final static int initialN = 128;
56   
57   /**
58    * Converts from the ascii "punicode" to a string.
59    */

60   public static String JavaDoc fromAscii(String JavaDoc source)
61   {
62     CharBuffer result = CharBuffer.allocate();
63     CharBuffer cb = CharBuffer.allocate();
64
65     int index = 0;
66     int length = source.length();
67     boolean isFirst = true;
68
69     try {
70       while (index < length) {
71     char ch = source.charAt(index + 0);
72       
73     if (isFirst && index + 4 < length &&
74         source.charAt(index + 0) == 'x' &&
75         source.charAt(index + 1) == 'n' &&
76         source.charAt(index + 2) == '-' &&
77         source.charAt(index + 3) == '-') {
78       int p = source.indexOf('.', index);
79       String JavaDoc seq;
80     
81       if (p < 0)
82         seq = source.substring(index + 4);
83       else
84         seq = source.substring(index + 4, p);
85     
86       decode(result, cb, seq);
87
88       index += 4 + seq.length();
89       continue;
90     }
91
92     index++;
93     
94     isFirst = false;
95
96     if (ch == '.') {
97       isFirst = true;
98
99       result.append(ch);
100     }
101     else
102       result.append(Character.toLowerCase(ch));
103       }
104
105       return result.close();
106     } catch (Throwable JavaDoc e) {
107       log.log(Level.WARNING, e.toString(), e);
108       
109       throw new RuntimeException JavaDoc(e);
110     }
111   }
112
113   /**
114    * Converts to the ascii "punicode".
115    */

116   public static String JavaDoc toAscii(String JavaDoc source)
117   {
118     CharBuffer result = CharBuffer.allocate();
119     CharBuffer cb = CharBuffer.allocate();
120
121     int head = 0;
122     int length = source.length();
123
124     while (head < length) {
125       boolean isAscii = true;
126
127       cb.clear();
128       
129       int i = head;
130       for (; i < length; i++) {
131     char ch = source.charAt(i);
132
133     if (ch == '.') {
134       cb.append(ch);
135       break;
136     }
137     else if (ch <= 0x7f)
138       cb.append(ch);
139     else {
140       isAscii = false;
141       break;
142     }
143       }
144
145       if (isAscii) {
146     head = i + 1;
147     result.append(cb);
148     continue;
149       }
150
151       cb.clear();
152       i = head;
153       for (; i < length; i++) {
154     char ch = source.charAt(i);
155
156     if (ch == '.')
157       break;
158
159     //cb.append(Character.toLowerCase(ch));
160
cb.append(ch);
161       }
162       head = i;
163
164       String JavaDoc seq = cb.toString();
165
166       cb.clear();
167
168       toAscii(cb, seq);
169
170       result.append(cb);
171     }
172
173     return result.close();
174   }
175
176   private static void decode(CharBuffer result, CharBuffer cb, String JavaDoc seq)
177   {
178     int length = seq.length();
179     int b = 0;
180
181     for (int i = 0; i < length; i++) {
182       char ch = seq.charAt(i);
183
184       if (ch == '-')
185     b = i;
186     }
187
188     for (int i = 0; i < b; i++) {
189       char ch = seq.charAt(i);
190       
191       cb.append(Character.toLowerCase(ch));
192     }
193
194     int in = b > 0 ? b + 1 : 0;
195     int i = 0;
196     int bias = initialBias;
197     int out = cb.length();
198     int n = initialN;
199
200     while (in < length) {
201       int oldi = i;
202       int w = 1;
203
204       for (int k = base; true; k += base) {
205     char ch = seq.charAt(in++);
206     int digit = DECODE[ch];
207
208     i += digit * w;
209
210     int t;
211     if (k <= bias)
212       t = tmin;
213     else if (bias + tmax <= k)
214       t = tmax;
215     else
216       t = k - bias;
217
218     if (digit < t)
219       break;
220
221     w *= (base - t);
222       }
223
224       bias = adapt(i - oldi, out + 1, oldi == 0);
225
226       n += i / (out + 1);
227       i %= (out + 1);
228
229       cb.append(' ');
230       char []cBuf = cb.getBuffer();
231
232       System.arraycopy(cBuf, i, cBuf, i + 1, out - i);
233       cBuf[i++] = Character.toLowerCase((char) n);
234
235       out++;
236     }
237
238     result.append(cb);
239   }
240
241   private static void toAscii(CharBuffer cb, String JavaDoc seq)
242   {
243     cb.append("xn--");
244
245     int length = seq.length();
246
247     int index = 0;
248     int n = initialN;
249     int delta = 0;
250     int bias = initialBias;
251     int b = 0; // # of basic code points
252

253     for (int i = 0; i < length; i++) {
254       char ch = seq.charAt(i);
255       if (ch < 0x80) {
256     cb.append(ch);
257     b++;
258       }
259     }
260
261     if (b > 0)
262       cb.append('-');
263
264     int h = b;
265
266     while (h < length) {
267       int m = 0xffff;
268       
269       for (int i = 0; i < length; i++) {
270     char ch = seq.charAt(i);
271
272     if (n <= ch && ch < m)
273       m = ch;
274       }
275
276       // XXX: overflow
277
delta = delta + (m - n) * (h + 1);
278       n = m;
279
280       for (int i = 0; i < length; i++) {
281     int ch = seq.charAt(i);
282
283     if (ch < n) {
284       delta++;
285     }
286
287     if (ch == n) {
288       int q = delta;
289       
290       for (int k = base; true; k += base) {
291         int t;
292
293         if (k <= bias)
294           t = tmin;
295         else if (bias + tmax <= k)
296           t = tmax;
297         else
298           t = k - bias;
299
300         if (q < t)
301           break;
302
303         cb.append(ENCODE[t + (q - t) % (base - t)]);
304         q = (q - t) / (base - t);
305       }
306
307       cb.append(ENCODE[q]);
308       bias = adapt(delta, h + 1, h == b);
309       delta = 0;
310       h++;
311     }
312       }
313
314       delta++;
315       n++;
316     }
317   }
318
319   private static int adapt(int delta, int nPoints, boolean isFirst)
320   {
321     int k;
322
323     delta = isFirst ? delta / damp : delta / 2;
324     delta += delta / nPoints;
325
326     for (k = 0; ((base - tmin) * tmax) / 2 < delta; k += base) {
327       delta /= base - tmin;
328     }
329
330     return k + (base - tmin + 1) * delta / (delta + skew);
331   }
332
333   static {
334     ENCODE = new char[36];
335
336     for (int i = 0; i < 26; i++) {
337       ENCODE[i] = (char) ('a' + i);
338     }
339
340     for (int i = 0; i < 10; i++) {
341       ENCODE[i + 26] = (char) ('0' + i);
342     }
343     
344     DECODE = new int[0x80];
345
346     for (int i = 0; i < 26; i++) {
347       DECODE[(char) ('a' + i)] = i;
348       DECODE[(char) ('A' + i)] = i;
349     }
350
351     for (int i = 0; i < 10; i++) {
352       DECODE[(char) ('0' + i)] = 26 + i;
353     }
354   }
355 }
356
Popular Tags