KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > es > NativeGlobal


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.es;
30
31 import com.caucho.es.parser.Parser;
32 import com.caucho.vfs.ReadStream;
33 import com.caucho.vfs.Vfs;
34
35 import java.io.IOException JavaDoc;
36
37 /**
38  * JavaScript object
39  */

40 class NativeGlobal extends Native {
41   static final int EVAL = 2;
42   static final int PARSE_INT = 3;
43   static final int PARSE_FLOAT = 4;
44   static final int ESCAPE = 5;
45   static final int UNESCAPE = 6;
46   static final int IS_NAN = 7;
47   static final int IS_FINITE = 8;
48
49   static final int PRINT = 9;
50   static final int SYSTEM = PRINT + 1;
51
52   /**
53    * Create a new object based on a prototype
54    */

55   NativeGlobal(String JavaDoc name, int n, int len)
56   {
57     super(name, len);
58
59     this.n = n;
60   }
61
62   /**
63    * Creates the native Object object
64    */

65   static void create(Global resin)
66   {
67     put(resin, "eval", EVAL, 1);
68     put(resin, "parseInt", PARSE_INT, 2);
69     put(resin, "parseFloat", PARSE_FLOAT, 1);
70     put(resin, "escape", ESCAPE, 1);
71     put(resin, "unescape", UNESCAPE, 1);
72     put(resin, "isNaN", IS_NAN, 1);
73     put(resin, "isFinite", IS_FINITE, 1);
74
75     put(resin, "print", PRINT, 1);
76     put(resin, "system", SYSTEM, 1);
77   }
78
79   private static void put(Global resin, String JavaDoc name, int n, int len)
80   {
81     ESId id = ESId.intern(name);
82
83     resin.addProperty(id, new NativeGlobal(name, n, len));
84   }
85
86   public ESBase call(Call eval, int length) throws Throwable JavaDoc
87   {
88     switch (n) {
89     case EVAL:
90       return eval(eval, length);
91
92     case PARSE_INT:
93       return parseInt(eval, length);
94
95     case PARSE_FLOAT:
96       if (length < 1)
97     return ESNumber.NaN;
98       else {
99     return ESNumber.create(ESString.parseFloat(eval.getArg(0).toStr()));
100       }
101
102     case ESCAPE:
103       return escape(eval, length);
104
105     case UNESCAPE:
106       return unescape(eval, length);
107
108     case IS_NAN:
109       if (length < 1)
110     return esUndefined;
111       else
112     return ESBoolean.create(Double.isNaN(eval.getArg(0).toNum()));
113
114     case IS_FINITE:
115       if (length < 1)
116     return esUndefined;
117       else {
118     double value = eval.getArg(0).toNum();
119     if (Double.isNaN(value))
120       return ESBoolean.create(false);
121     else if (value == 1.0/0.0)
122       return ESBoolean.create(false);
123     else if (value == -1.0/0.0)
124       return ESBoolean.create(false);
125     else
126       return ESBoolean.create(true);
127       }
128
129     case PRINT:
130       System.out.print(eval.getArg(0).toStr().toString());
131       return esNull;
132
133     case SYSTEM:
134       String JavaDoc arg = eval.getArg(0).toStr().toString();
135       String JavaDoc []args = new String JavaDoc[3];
136       Process JavaDoc process;
137       try {
138     args[0] = "sh";
139     args[1] = "-c";
140     args[2] = arg;
141     process = Runtime.getRuntime().exec(args);
142     return ESNumber.create(process.waitFor());
143       } catch (Exception JavaDoc e) {
144     throw new ESWrapperException(e);
145       }
146
147     default:
148       throw new ESException("Unknown object function");
149     }
150   }
151
152   private ESBase eval(Call eval, int length) throws Throwable JavaDoc
153   {
154     if (length < 1)
155       return esUndefined;
156
157     ESBase arg = eval.getArg(0);
158     if (! (arg instanceof ESString))
159       return arg;
160
161     String JavaDoc string = arg.toString();
162
163     Global resin = Global.getGlobalProto();
164     ESBase context = eval.getFunctionContext();
165     Script script = null;
166     ReadStream is = null;
167     try {
168       Parser parser = new Parser();
169       is = Vfs.openString(string);
170       script = parser.parseEval(is, "eval", 1);
171     } catch (IOException JavaDoc e) {
172       e.printStackTrace();
173     } finally {
174       if (is != null)
175         is.close();
176     }
177
178     ESCallable jsClass = script.initClass(resin, eval.getGlobal());
179     
180     return jsClass.call(2, eval.caller, 0);
181   }
182
183   private ESBase parseInt(Call eval, int length) throws Throwable JavaDoc
184   {
185     if (length < 1)
186       return ESNumber.NaN;
187
188     ESString string = eval.getArg(0).toStr();
189     int len = string.length();
190
191     int i = 0;
192     for (; i < len && Character.isSpaceChar(string.charAt(i)); i++) {
193     }
194
195     int sign = 1;
196     if (i < len && string.charAt(i) == '+') {
197       i++;
198     } else if (i < len && string.charAt(i) == '-') {
199       sign = -1;
200       i++;
201     }
202
203     int radix = 0;
204     if (length > 1) {
205       radix = eval.getArg(1).toInt32();
206       if (radix == 0) {
207       }
208       else if (radix < 2 || radix > 36)
209     return ESNumber.NaN;
210       else if (radix == 16 && i + 1 < length &&
211            string.charAt(i) == '0' &&
212            (string.charAt(i + 1) == 'x' ||
213         string.charAt(i + 1) == 'X'))
214     i += 2;
215     }
216     
217     if (radix != 0) {
218     }
219     else if (i >= len)
220       radix = 10;
221     else if (string.charAt(i) != '0')
222       radix = 10;
223     else if (i + 1 < len &&
224          (string.charAt(i + 1) == 'x' || string.charAt(i + 1) == 'X')) {
225       radix = 16;
226       i += 2;
227     } else {
228       radix = 8;
229     }
230
231     long value = 0;
232     boolean hasDigit = false;
233     for (; i < len; i++) {
234       int ch = string.charAt(i);
235
236       if (radix <= 10 && ('0' <= ch && ch <= '0' + radix - 1)) {
237     value = radix * value + string.charAt(i) - '0';
238     hasDigit = true;
239       } else if (radix > 10 && ('0' <= ch && ch <= '9')) {
240     value = radix * value + string.charAt(i) - '0';
241     hasDigit = true;
242       } else if (radix > 10 && ('a' <= ch && ch <= 'a' + radix - 11)) {
243     value = radix * value + string.charAt(i) - 'a' + 10;
244     hasDigit = true;
245       } else if (radix > 10 && ('A' <= ch && ch <= 'A' + radix - 11)) {
246     value = radix * value + string.charAt(i) - 'A' + 10;
247     hasDigit = true;
248       } else
249     break;
250     }
251
252     if (hasDigit)
253       return ESNumber.create((double) sign * value);
254     else
255       return ESNumber.NaN;
256   }
257
258   static ESBase escape(Call eval, int length) throws Throwable JavaDoc
259   {
260     if (length < 1)
261       return esUndefined;
262     
263     ESString string = eval.getArg(0).toStr();
264     StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc();
265
266     for (int i = 0; i < string.length(); i++) {
267       int ch = string.charAt(i);
268
269       if (ch >= 'a' && ch <= 'z' ||
270       ch >= 'A' && ch <= 'Z' ||
271       ch >= '0' && ch <= '9' ||
272       ch == '@' || ch == '*' || ch == '.' || ch == '_' ||
273       ch == '+' || ch == '-' || ch == '/') {
274     sbuf.append((char) ch);
275       } else if (ch < 256) {
276     sbuf.append('%');
277     sbuf.append(Integer.toHexString(ch >> 4));
278     sbuf.append(Integer.toHexString(ch & 0xf));
279       } else {
280     sbuf.append("%u");
281     sbuf.append(Integer.toHexString(ch >> 12));
282     sbuf.append(Integer.toHexString((ch >> 8) & 0xf));
283     sbuf.append(Integer.toHexString((ch >> 4) & 0xf));
284     sbuf.append(Integer.toHexString(ch & 0xf));
285       }
286     }
287
288     return ESString.create(sbuf.toString());
289   }
290
291   static ESBase unescape(Call eval, int length) throws Throwable JavaDoc
292   {
293     if (length < 1)
294       return esUndefined;
295     
296     ESString string = eval.getArg(0).toStr();
297     StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc();
298
299     for (int i = 0; i < string.length(); i++) {
300       int ch = string.charAt(i);
301
302       if (ch == '%' && i + 2 < string.length()) {
303     int limit = 2;
304     int start = 1;
305
306     if (string.charAt(i + 1) == 'u') {
307       limit = 4;
308       start = 2;
309     }
310
311     int newCh = 0;
312     int j = 0;
313     for (; j < limit && i + j + start < string.length(); j++) {
314       if ((ch = string.charAt(i + j + start)) >= '0' && ch <= '9')
315         newCh = 16 * newCh + ch - '0';
316       else if (ch >= 'a' && ch <= 'f')
317         newCh = 16 * newCh + ch - 'a' + 10;
318       else if (ch >= 'A' && ch <= 'F')
319         newCh = 16 * newCh + ch - 'A' + 10;
320       else
321         break;
322     }
323
324     if (j != limit) {
325       sbuf.append('%');
326     } else {
327       sbuf.append((char) newCh);
328       i += limit + start - 1;
329     }
330       }
331       else
332     sbuf.append((char) ch);
333     }
334
335     return ESString.create(sbuf.toString());
336   }
337 }
338
Popular Tags