KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > quercus > lib > MiscModule


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  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.quercus.lib;
31
32 import com.caucho.quercus.Quercus;
33 import com.caucho.quercus.QuercusException;
34 import com.caucho.quercus.QuercusModuleException;
35 import com.caucho.quercus.annotation.Optional;
36 import com.caucho.quercus.annotation.Reference;
37 import com.caucho.quercus.annotation.UsesSymbolTable;
38 import com.caucho.quercus.env.*;
39 import com.caucho.quercus.lib.file.FileModule;
40 import com.caucho.quercus.module.AbstractQuercusModule;
41 import com.caucho.quercus.program.QuercusProgram;
42 import com.caucho.util.L10N;
43 import com.caucho.util.RandomUtil;
44 import com.caucho.vfs.*;
45
46 import java.io.IOException JavaDoc;
47 import java.io.InputStream JavaDoc;
48 import java.io.OutputStream JavaDoc;
49 import java.util.ArrayList JavaDoc;
50 import java.util.Map JavaDoc;
51 import java.util.logging.Level JavaDoc;
52 import java.util.logging.Logger JavaDoc;
53 import java.util.regex.Matcher JavaDoc;
54 import java.util.regex.Pattern JavaDoc;
55
56 /**
57  * PHP mysql routines.
58  */

59 public class MiscModule extends AbstractQuercusModule {
60   private static final L10N L = new L10N(MiscModule.class);
61   private static final Logger JavaDoc log
62     = Logger.getLogger(MiscModule.class.getName());
63
64   /**
65    * Escapes characters in a string.
66    */

67   public static String JavaDoc escapeshellcmd(String JavaDoc command)
68   {
69     StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
70     int len = command.length();
71     
72     boolean hasApos = false;
73     boolean hasQuot = false;
74
75     for (int i = 0; i < len; i++) {
76       char ch = command.charAt(i);
77
78       switch (ch) {
79       case '#': case '&': case ';': case '`': case '|':
80       case '*': case '?': case '~': case '<': case '>':
81       case '^': case '(': case ')': case '[': case ']':
82       case '{': case '}': case '$': case '\\': case ',':
83       case 0x0a: case 0xff:
84     sb.append('\\');
85     sb.append(ch);
86     break;
87       case '\'':
88     hasApos = ! hasApos;
89     sb.append(ch);
90     break;
91       case '\"':
92     hasQuot = ! hasQuot;
93     sb.append(ch);
94     break;
95       default:
96     sb.append(ch);
97       }
98     }
99
100     String JavaDoc result = sb.toString();
101
102     if (hasApos) {
103       int p = result.lastIndexOf('\'');
104       result = result.substring(0, p) + "\\" + result.substring(p);
105     }
106
107     if (hasQuot) {
108       int p = result.lastIndexOf('\"');
109       result = result.substring(0, p) + "\\" + result.substring(p);
110     }
111
112     return result;
113   }
114
115   /**
116    * Escapes characters in a string.
117    */

118   public static String JavaDoc escapeshellarg(String JavaDoc arg)
119   {
120     StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
121
122     sb.append('\'');
123     
124     int len = arg.length();
125
126     for (int i = 0; i < len; i++) {
127       char ch = arg.charAt(i);
128
129       if (ch == '\'')
130     sb.append("\\\'");
131       else
132     sb.append(ch);
133     }
134
135     sb.append('\'');
136
137     return sb.toString();
138   }
139
140   /**
141    * Comples and evaluates an expression.
142    */

143   @UsesSymbolTable
144   public Value eval(Env env, String JavaDoc code)
145   {
146     try {
147       if (log.isLoggable(Level.FINER))
148     log.finer(code);
149       
150       Quercus quercus = env.getQuercus();
151       
152       QuercusProgram program = quercus.parseCode(code);
153       
154       Value value = program.execute(env);
155       
156       return value;
157     } catch (IOException JavaDoc e) {
158       throw new QuercusException(e);
159     }
160   }
161
162   /**
163    * packs the format into a binary.
164    */

165   public Value pack(Env env, String JavaDoc format, Value []args)
166   {
167     try {
168       ArrayList JavaDoc<PackSegment> segments = parsePackFormat(format);
169
170       BinaryBuilderValue bb = new BinaryBuilderValue();
171
172       int i = 0;
173       for (PackSegment segment : segments) {
174     i = segment.pack(env, bb, i, args);
175       }
176
177       return bb;
178     } catch (IOException JavaDoc e) {
179       throw new QuercusModuleException(e);
180     }
181   }
182
183   /**
184    * packs the format into a binary.
185    */

186   public Value unpack(Env env, String JavaDoc format, InputStream JavaDoc is)
187   {
188     try {
189       ArrayList JavaDoc<PackSegment> segments = parseUnpackFormat(format);
190
191       ArrayValue array = new ArrayValueImpl();
192
193       for (PackSegment segment : segments) {
194     segment.unpack(env, array, is);
195       }
196
197       return array;
198     } catch (IOException JavaDoc e) {
199       throw new QuercusModuleException(e);
200     }
201   }
202
203   /**
204    * Comples and evaluates an expression.
205    */

206   public Value resin_debug(String JavaDoc code)
207   {
208     log.info(code);
209
210     return NullValue.NULL;
211   }
212
213   /**
214    * Comples and evaluates an expression.
215    */

216   public Value resin_thread_dump()
217   {
218     Thread.dumpStack();
219
220     return NullValue.NULL;
221   }
222
223   /**
224    * Dumps the stack.
225    */

226   public static Value dump_stack(Env env)
227   {
228     try {
229       Exception JavaDoc e = new Exception JavaDoc("Stack trace");
230       e.fillInStackTrace();
231
232       WriteStream out = env.getPwd().lookup("stderr:").openWrite();
233       try {
234     e.printStackTrace(out.getPrintWriter());
235     //ScriptStackTrace.printStackTrace(e, out.getPrintWriter());
236
} finally {
237     out.close();
238       }
239
240       return NullValue.NULL;
241     } catch (IOException JavaDoc e) {
242       throw new QuercusModuleException(e);
243     }
244   }
245
246   /**
247    * Execute a system command.
248    */

249   public static String JavaDoc exec(Env env, String JavaDoc command,
250                 @Optional Value output,
251                 @Optional @Reference Value result)
252   {
253     String JavaDoc []args = new String JavaDoc[3];
254
255     try {
256       args[0] = "sh";
257       args[1] = "-c";
258       args[2] = command;
259       Process JavaDoc process = Runtime.getRuntime().exec(args);
260
261       InputStream JavaDoc is = process.getInputStream();
262       OutputStream JavaDoc os = process.getOutputStream();
263       os.close();
264
265       StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
266       String JavaDoc line = "";
267
268       int ch;
269       boolean hasCr = false;
270       while ((ch = is.read()) >= 0) {
271     if (ch == '\n') {
272       if (! hasCr) {
273         line = sb.toString();
274         sb.setLength(0);
275         if (output != null)
276           output.put(new StringValueImpl(line));
277       }
278       hasCr = false;
279     }
280     else if (ch == '\r') {
281       line = sb.toString();
282       sb.setLength(0);
283       output.put(new StringValueImpl(line));
284       hasCr = true;
285     }
286     else
287       sb.append((char) ch);
288       }
289
290       if (sb.length() > 0) {
291     line = sb.toString();
292     sb.setLength(0);
293     output.put(new StringValueImpl(line));
294       }
295
296       is.close();
297
298       int status = process.waitFor();
299
300       result.set(new LongValue(status));
301
302       return line;
303     } catch (Exception JavaDoc e) {
304       env.warning(e.getMessage(), e);
305
306       return null;
307     }
308   }
309
310   /**
311    * Execute a system command.
312    */

313   public static Value shell_exec(Env env, String JavaDoc command)
314   {
315     String JavaDoc []args = new String JavaDoc[3];
316
317     try {
318       args[0] = "sh";
319       args[1] = "-c";
320       args[2] = command;
321       Process JavaDoc process = Runtime.getRuntime().exec(args);
322
323       InputStream JavaDoc is = process.getInputStream();
324       OutputStream JavaDoc os = process.getOutputStream();
325       os.close();
326
327       StringBuilderValue sb = new StringBuilderValue();
328
329       int ch;
330       boolean hasCr = false;
331       while ((ch = is.read()) >= 0) {
332     sb.append((char) ch);
333       }
334
335       is.close();
336
337       int status = process.waitFor();
338
339       return sb;
340     } catch (Exception JavaDoc e) {
341       env.warning(e.getMessage(), e);
342
343       return NullValue.NULL;
344     }
345   }
346
347   /**
348    * Execute a system command.
349    */

350   public static void passthru(Env env, String JavaDoc command,
351                    @Optional @Reference Value result)
352   {
353
354     try {
355       String JavaDoc []args = new String JavaDoc[3];
356       args[0] = "sh";
357       args[1] = "-c";
358       args[2] = command;
359
360       ProcessBuilder JavaDoc processBuilder = new ProcessBuilder JavaDoc(args);
361       processBuilder.redirectErrorStream(true);
362       final Process JavaDoc process = processBuilder.start();
363
364       try {
365         InputStream JavaDoc is = process.getInputStream();
366         OutputStream JavaDoc os = process.getOutputStream();
367         os.close();
368
369         env.getOut().writeStream(is);
370         is.close();
371
372         int status = process.waitFor();
373       }
374       finally {
375         process.destroy();
376       }
377     } catch (Exception JavaDoc e) {
378       env.warning(e.getMessage(), e);
379     }
380   }
381
382   /**
383    * Returns the disconnect ignore setting
384    */

385   public static int ignore_user_abort(@Optional boolean set)
386   {
387     return 0;
388   }
389
390   /**
391    * Returns a unique id.
392    */

393   public String JavaDoc uniqid(@Optional String JavaDoc prefix, @Optional boolean moreEntropy)
394   {
395     StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
396
397     if (prefix != null)
398       sb.append(prefix);
399
400     addUnique(sb);
401
402     if (moreEntropy)
403       addUnique(sb);
404
405     return sb.toString();
406   }
407
408   private void addUnique(StringBuilder JavaDoc sb)
409   {
410     long value = RandomUtil.getRandomLong();
411
412     if (value < 0)
413       value = -value;
414
415     int limit = 13;
416
417     for (; limit > 0; limit--) {
418       long digit = value % 26;
419       value = value / 26;
420
421       sb.append((char) ('a' + digit));
422     }
423   }
424
425   /**
426    * Sleep for a number of microseconds.
427    */

428   public static Value usleep(long microseconds)
429   {
430     try {
431       Thread.sleep(microseconds / 1000);
432     } catch (Throwable JavaDoc e) {
433     }
434
435     return NullValue.NULL;
436   }
437
438   /**
439    * Sleep for a number of seconds.
440    */

441   public static long sleep(long seconds)
442   {
443     try {
444       Thread.sleep(seconds * 1000);
445     } catch (Throwable JavaDoc e) {
446     }
447
448     return seconds;
449   }
450
451   /**
452    * Returns an array detailing what the browser is capable of.
453    * A general browscap.ini file can be used.
454    *
455    * @param env
456    * @param user_agent
457    * @param return_array
458    */

459   public static Value get_browser(
460                        Env env,
461                        @Optional() String JavaDoc user_agent,
462                        @Optional() boolean return_array)
463   {
464     if (user_agent == null ||
465         user_agent.length() == 0)
466       user_agent = env.getRequest().getHeader("User-Agent");
467
468     if (user_agent == null) {
469       env.warning(L.l("HTTP_USER_AGENT not set."));
470       return BooleanValue.FALSE;
471     }
472
473     Value browscap = env.getConfigVar("browscap");
474     if (browscap == null) {
475       env.warning(L.l("Browscap path not set in PHP.ini."));
476       return BooleanValue.FALSE;
477     }
478
479     Path path = env.lookup(browscap.toString());
480     if (path == null) {
481       env.warning(L.l("Browscap file not found."));
482       return BooleanValue.FALSE;
483     }
484
485     Value ini = FileModule.parse_ini_file(env, path, true);
486     if (ini == BooleanValue.FALSE)
487       return BooleanValue.FALSE;
488
489     return getBrowserReport(
490         env, ini.toArrayValue(env), user_agent, return_array);
491   }
492
493   private static Value getBrowserReport(
494                        Env env,
495                        ArrayValue browsers,
496                        String JavaDoc user_agent,
497                        boolean return_array)
498   {
499     StringValue patternMatched = StringValue.EMPTY;
500     String JavaDoc regExpMatched = null;
501
502     for (Map.Entry JavaDoc<Value,Value> entry : browsers.entrySet()) {
503       StringValue pattern = entry.getKey().toStringValue();
504       
505       if (pattern.toString().equals(user_agent)) {
506         patternMatched = pattern;
507         regExpMatched = null;
508         break;
509       }
510
511       String JavaDoc regExp = formatBrowscapRegexp(pattern);
512       Matcher JavaDoc m = Pattern.compile(regExp).matcher(user_agent);
513
514       // Want the longest matching pattern.
515
if (m.matches()) {
516         if (pattern.length() > patternMatched.length()) {
517           patternMatched = pattern;
518           regExpMatched = regExp;
519         }
520       }
521     }
522
523     if (patternMatched.length() == 0)
524       return BooleanValue.FALSE;
525
526     return prepareBrowserReport(env, browsers, patternMatched, regExpMatched,
527         user_agent, return_array);
528   }
529
530   private static Value prepareBrowserReport(
531                        Env env,
532                        ArrayValue browsers,
533                        StringValue patternMatched,
534                        String JavaDoc regExpMatched,
535                        String JavaDoc user_agent,
536                        boolean return_array)
537   {
538     ArrayValue capabilities = browsers.get(patternMatched).toArrayValue(env);
539
540     if (regExpMatched == null)
541       capabilities.put(
542           new StringValueImpl("browser_name_regex"), patternMatched);
543     else
544       capabilities.put("browser_name_regex", regExpMatched);
545     capabilities.put(
546         new StringValueImpl("browser_name_pattern"), patternMatched);
547
548     addBrowserCapabilities(env, browsers,
549         capabilities.get(new StringValueImpl("parent")), capabilities);
550
551     if (return_array) {
552       ArrayValue array = new ArrayValueImpl();
553       array.put(new StringValueImpl(user_agent), capabilities);
554       return array;
555     }
556
557     ObjectValue object = env.createObject();
558     for (Map.Entry JavaDoc<Value,Value> entry : capabilities.entrySet()) {
559       object.putFieldInit(env, entry.getKey().toString(), entry.getValue());
560     }
561     
562     return object;
563   }
564   
565   private static void addBrowserCapabilities(
566                        Env env,
567                        ArrayValue browsers,
568                        Value browser,
569                        ArrayValue cap)
570   {
571     if (browser == UnsetValue.UNSET)
572       return;
573
574     Value field = null;
575     if ((field = browsers.get(browser)) == UnsetValue.UNSET)
576       return;
577
578     ArrayValue browserCapabilities = field.toArrayValue(env);
579     StringValue parentString = new StringValueImpl("parent");
580     
581     for (Map.Entry JavaDoc<Value,Value> entry : browserCapabilities.entrySet()) {
582       Value key = entry.getKey();
583
584       if (key.equals(parentString)) {
585         addBrowserCapabilities(
586             env, browsers, entry.getValue(), cap);
587       }
588       else if (cap.containsKey(key) == null)
589         cap.put(key, entry.getValue());
590     }
591   }
592
593   private static String JavaDoc formatBrowscapRegexp(StringValue key)
594   {
595     int length = key.length();
596   
597     StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
598     for (int i = 0; i < length; i++) {
599       char ch = key.charAt(i);
600       switch (ch) {
601         case '*':
602           sb.append('.');
603           sb.append('*');
604           break;
605         case '?':
606           sb.append('.');
607           break;
608         case '.':
609           sb.append('\\');
610           sb.append('.');
611           break;
612         case '+':
613           sb.append('\\');
614           sb.append('+');
615           break;
616         case '(':
617           sb.append('\\');
618           sb.append('(');
619           break;
620          case ')':
621           sb.append('\\');
622           sb.append(')');
623           break;
624         case '{':
625           sb.append('\\');
626           sb.append('{');
627           break;
628          case '}':
629           sb.append('\\');
630           sb.append('}');
631           break;
632         case ']':
633           sb.append('\\');
634           sb.append(']');
635           break;
636         case '[':
637           sb.append('\\');
638           sb.append('[');
639           break;
640         case '\\':
641           sb.append('\\');
642           sb.append('\\');
643           break;
644         case '^':
645           sb.append('\\');
646           sb.append('^');
647           break;
648         case '$':
649           sb.append('\\');
650           sb.append('$');
651           break;
652         case '&':
653           sb.append('\\');
654           sb.append('&');
655           break;
656         case '|':
657           sb.append('\\');
658           sb.append('|');
659           break;
660         default:
661           sb.append(ch);
662       }
663     }
664     
665     return sb.toString();
666   }
667
668   /**
669    * Execute a system command.
670    */

671   public static String JavaDoc system(Env env, String JavaDoc command,
672                   @Optional @Reference Value result)
673   {
674     return exec(env, command, null, result);
675   }
676
677   private static ArrayList JavaDoc<PackSegment> parsePackFormat(String JavaDoc format)
678   {
679     ArrayList JavaDoc<PackSegment> segments = new ArrayList JavaDoc<PackSegment>();
680
681     int length = format.length();
682     for (int i = 0; i < length; i++) {
683       char ch = format.charAt(i);
684       
685       int count = 0;
686       char ch1 = ' ';
687       for (i++;
688        i < length && '0' <= (ch1 = format.charAt(i)) && ch1 <= '9';
689        i++) {
690     count = 10 * count + ch1 - '0';
691       }
692
693       if (ch1 == '*' && count == 0) {
694     i++;
695     count = Integer.MAX_VALUE;
696       }
697       else if (count == 0)
698     count = 1;
699
700       if (i < length)
701     i--;
702
703       switch (ch) {
704       case 'a':
705     segments.add(new SpacePackSegment(count, (byte) 0));
706     break;
707       case 'A':
708     segments.add(new SpacePackSegment(count, (byte) 0x20));
709     break;
710       case 'h':
711     segments.add(new RevHexPackSegment(count));
712     break;
713       case 'H':
714     segments.add(new HexPackSegment(count));
715     break;
716       case 'c':
717       case 'C':
718     segments.add(new BigEndianPackSegment(count, 1));
719     break;
720       case 's':
721       case 'n':
722       case 'S':
723     segments.add(new BigEndianPackSegment(count, 2));
724     break;
725       case 'v':
726     segments.add(new LittleEndianPackSegment(count, 2));
727     break;
728       case 'l':
729       case 'L':
730       case 'N':
731     segments.add(new BigEndianPackSegment(count, 4));
732     break;
733       case 'V':
734     segments.add(new LittleEndianPackSegment(count, 4));
735     break;
736       case 'i':
737       case 'I':
738     segments.add(new BigEndianPackSegment(count, 8));
739     break;
740       case 'd':
741     segments.add(new DoublePackSegment(count));
742     break;
743       case 'f':
744     segments.add(new FloatPackSegment(count));
745     break;
746       case 'x':
747     segments.add(new NullPackSegment(count));
748     break;
749       case '@':
750     segments.add(new PositionPackSegment(count));
751     break;
752       }
753     }
754
755     return segments;
756   }
757
758   private static ArrayList JavaDoc<PackSegment> parseUnpackFormat(String JavaDoc format)
759   {
760     ArrayList JavaDoc<PackSegment> segments = new ArrayList JavaDoc<PackSegment>();
761
762     int length = format.length();
763     for (int i = 0; i < length; i++) {
764       char ch = format.charAt(i);
765       
766       int count = 0;
767       char ch1 = ' ';
768       for (i++;
769        i < length && '0' <= (ch1 = format.charAt(i)) && ch1 <= '9';
770        i++) {
771     count = 10 * count + ch1 - '0';
772       }
773       
774       if (count == 0)
775     count = 1;
776
777       if (i < length)
778     i--;
779
780       StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
781       
782       for (i++; i < length && (ch1 = format.charAt(i)) != '/'; i++) {
783     sb.append(ch1);
784       }
785
786       String JavaDoc name = sb.toString();
787
788       switch (ch) {
789       case 'a':
790     segments.add(new SpacePackSegment(name, count, (byte) 0));
791     break;
792       case 'A':
793     segments.add(new SpacePackSegment(name, count, (byte) 0x20));
794     break;
795       case 'h':
796     segments.add(new RevHexPackSegment(name, count));
797     break;
798       case 'H':
799     segments.add(new HexPackSegment(name, count));
800     break;
801       case 'c':
802     segments.add(new BigEndianPackSegment(name, count, 1, true));
803     break;
804       case 'C':
805     segments.add(new BigEndianPackSegment(name, count, 1, false));
806     break;
807       case 's':
808     segments.add(new BigEndianPackSegment(name, count, 2, true));
809     break;
810       case 'n':
811       case 'S':
812     segments.add(new BigEndianPackSegment(name, count, 2, false));
813     break;
814       case 'v':
815     segments.add(new LittleEndianPackSegment(name, count, 2));
816     break;
817       case 'l':
818     segments.add(new BigEndianPackSegment(name, count, 4, true));
819     break;
820       case 'L':
821       case 'N':
822     segments.add(new BigEndianPackSegment(name, count, 4, false));
823     break;
824       case 'V':
825     segments.add(new LittleEndianPackSegment(name, count, 4));
826     break;
827       case 'i':
828       case 'I':
829     segments.add(new BigEndianPackSegment(name, count, 8, false));
830     break;
831       case 'd':
832     segments.add(new DoublePackSegment(name, count));
833     break;
834       case 'f':
835     segments.add(new FloatPackSegment(name, count));
836     break;
837       case 'x':
838     segments.add(new NullPackSegment(name, count));
839     break;
840       case '@':
841     segments.add(new PositionPackSegment(name, count));
842     break;
843       }
844     }
845
846     return segments;
847   }
848
849   abstract static class PackSegment {
850     abstract public int pack(Env env, BinaryBuilderValue bb,
851                   int i, Value []args)
852       throws IOException JavaDoc;
853     
854     abstract public void unpack(Env env, ArrayValue array, InputStream JavaDoc is)
855       throws IOException JavaDoc;
856   }
857
858   static class SpacePackSegment extends PackSegment {
859     private final StringValue _name;
860     private final int _length;
861     private final byte _pad;
862
863     SpacePackSegment(int length, byte pad)
864     {
865       this("", length, pad);
866     }
867
868     SpacePackSegment(String JavaDoc name, int length, byte pad)
869     {
870       _name = new StringValueImpl(name);
871       _length = length;
872       _pad = pad;
873     }
874     
875     public int pack(Env env, BinaryBuilderValue bb, int i, Value []args)
876       throws IOException JavaDoc
877     {
878       Value arg;
879
880       if (i < args.length) {
881     arg = args[i];
882     i++;
883       }
884       else {
885     env.warning("a: not enough arguments");
886
887     return i;
888       }
889
890       InputStream JavaDoc is = arg.toInputStream();
891
892       int length = _length;
893
894       for (int j = 0; j < length; j++) {
895     int ch = is.read();
896
897     if (ch >= 0)
898       bb.appendByte(ch);
899     else if (length == Integer.MAX_VALUE)
900       return i;
901     else
902       bb.appendByte(_pad);
903       }
904
905       return i;
906     }
907     
908     public void unpack(Env env, ArrayValue result, InputStream JavaDoc is)
909       throws IOException JavaDoc
910     {
911       BinaryBuilderValue bb = new BinaryBuilderValue();
912       for (int i = 0; i < _length; i++) {
913     int ch = is.read();
914
915     if (ch == _pad) {
916     }
917     else if (ch >= 0)
918       bb.appendByte(ch);
919     else
920       break;
921       }
922
923       result.put(_name, bb);
924     }
925   }
926
927   static class HexPackSegment extends PackSegment {
928     private final StringValue _name;
929     private final int _length;
930
931     HexPackSegment(int length)
932     {
933       this("", length);
934     }
935
936     HexPackSegment(String JavaDoc name, int length)
937     {
938       _name = new StringValueImpl(name);
939       _length = length;
940     }
941     
942     public int pack(Env env, BinaryBuilderValue bb, int i, Value []args)
943       throws IOException JavaDoc
944     {
945       Value arg;
946
947       if (i < args.length) {
948     arg = args[i];
949     i++;
950       }
951       else {
952     env.warning("a: not enough arguments");
953
954     return i;
955       }
956
957       StringValue s = arg.toStringValue();
958
959       int strlen = s.length();
960
961       if (_length == Integer.MAX_VALUE) {
962       }
963       else if (strlen < _length) {
964     env.warning("not enough characters in hex string");
965
966     return i;
967       }
968       else if (_length < strlen)
969     strlen = _length;
970       
971       int tail = strlen / 2;
972       for (int j = 0; j < tail; j++) {
973     int d = 0;
974     
975     char ch = s.charAt(2 * j);
976
977     d += 16 * hexToDigit(env, ch);
978     
979     ch = s.charAt(2 * j + 1);
980
981     d += hexToDigit(env, ch);
982
983     bb.appendByte(d);
984       }
985       
986       if ((strlen & 1) == 1) {
987     int d = 16 * hexToDigit(env, s.charAt(strlen - 1));
988
989     bb.appendByte(d);
990       }
991
992       return i;
993     }
994     
995     public void unpack(Env env, ArrayValue result, InputStream JavaDoc is)
996       throws IOException JavaDoc
997     {
998       StringBuilderValue sb = new StringBuilderValue();
999       for (int i = _length / 2 - 1; i >= 0; i--) {
1000    int ch = is.read();
1001
1002    sb.append(digitToHex(ch >> 4));
1003    sb.append(digitToHex(ch));
1004      }
1005
1006      result.put(_name, sb);
1007    }
1008  }
1009
1010  static class RevHexPackSegment extends PackSegment {
1011    private final StringValue _name;
1012    private final int _length;
1013
1014    RevHexPackSegment(int length)
1015    {
1016      this("", length);
1017    }
1018
1019    RevHexPackSegment(String JavaDoc name, int length)
1020    {
1021      _name = new StringValueImpl(name);
1022      _length = length;
1023    }
1024    
1025    public int pack(Env env, BinaryBuilderValue bb, int i, Value []args)
1026      throws IOException JavaDoc
1027    {
1028      Value arg;
1029
1030      if (i < args.length) {
1031    arg = args[i];
1032    i++;
1033      }
1034      else {
1035    env.warning("a: not enough arguments");
1036
1037    return i;
1038      }
1039
1040      StringValue s = arg.toStringValue();
1041
1042      int strlen = s.length();
1043
1044      if (_length == Integer.MAX_VALUE) {
1045      }
1046      else if (strlen < _length) {
1047    env.warning("not enough characters in hex string");
1048
1049    return i;
1050      }
1051      else if (_length < strlen)
1052    strlen = _length;
1053      
1054      int tail = strlen / 2;
1055      for (int j = 0; j < tail; j++) {
1056    int d = 0;
1057    
1058    char ch = s.charAt(2 * j);
1059
1060    d += hexToDigit(env, ch);
1061    
1062    ch = s.charAt(2 * j + 1);
1063
1064    d += 16 * hexToDigit(env, ch);
1065
1066    bb.appendByte(d);
1067      }
1068      
1069      if ((strlen & 1) == 1) {
1070    int d = hexToDigit(env, s.charAt(strlen - 1));
1071
1072    bb.appendByte(d);
1073      }
1074
1075      return i;
1076    }
1077    
1078    public void unpack(Env env, ArrayValue result, InputStream JavaDoc is)
1079      throws IOException JavaDoc
1080    {
1081      StringBuilderValue sb = new StringBuilderValue();
1082      for (int i = _length / 2 - 1; i >= 0; i--) {
1083    int ch = is.read();
1084
1085    sb.append(digitToHex(ch));
1086    sb.append(digitToHex(ch >> 4));
1087      }
1088
1089      result.put(_name, sb);
1090    }
1091  }
1092
1093  static class BigEndianPackSegment extends PackSegment {
1094    private final String JavaDoc _name;
1095    private final int _length;
1096    private final int _bytes;
1097    private final boolean _isSigned;
1098
1099    BigEndianPackSegment(int length, int bytes)
1100    {
1101      _name = "";
1102      _length = length;
1103      _bytes = bytes;
1104      _isSigned = false;
1105    }
1106
1107    BigEndianPackSegment(String JavaDoc name, int length, int bytes, boolean isSigned)
1108    {
1109      _name = name;
1110      _length = length;
1111      _bytes = bytes;
1112      _isSigned = isSigned;
1113    }
1114    
1115    public int pack(Env env, BinaryBuilderValue bb, int i, Value []args)
1116      throws IOException JavaDoc
1117    {
1118      for (int j = 0; j < _length; j++) {
1119    Value arg;
1120
1121    if (i < args.length) {
1122      arg = args[i];
1123      i++;
1124    }
1125    else if (_length == Integer.MAX_VALUE)
1126      return i;
1127    else {
1128      env.warning("a: not enough arguments");
1129
1130      return i;
1131    }
1132 
1133    long v = arg.toLong();
1134
1135    for (int k = _bytes - 1; k >= 0; k--) {
1136      bb.appendByte((int) (v >> (8 * k)));
1137    }
1138      }
1139
1140      return i;
1141    }
1142    
1143    public void unpack(Env env, ArrayValue result, InputStream JavaDoc is)
1144      throws IOException JavaDoc
1145    {
1146      for (int j = 0; j < _length; j++) {
1147    Value key;
1148
1149    if (_name == "")
1150      key = LongValue.create(j);
1151    else if (_length == 1)
1152      key = new StringValueImpl(_name);
1153    else {
1154      StringBuilderValue sb = new StringBuilderValue();
1155      sb.append(_name);
1156      sb.append(j);
1157
1158      key = sb;
1159    }
1160    
1161    long v = 0;
1162
1163    for (int k = 0; k < _bytes; k++) {
1164      long d = is.read() & 0xff;
1165
1166      v = 256 * v + d;
1167    }
1168
1169    if (_isSigned) {
1170      switch (_bytes) {
1171      case 1:
1172        v = (byte) v;
1173        break;
1174      case 2:
1175        v = (short) v;
1176        break;
1177      case 4:
1178        v = (int) v;
1179        break;
1180      }
1181    }
1182
1183    result.put(key, LongValue.create(v));
1184      }
1185    }
1186  }
1187
1188  static class LittleEndianPackSegment extends PackSegment {
1189    private final String JavaDoc _name;
1190    private final int _length;
1191    private final int _bytes;
1192
1193    LittleEndianPackSegment(int length, int bytes)
1194    {
1195      _name = "";
1196      _length = length;
1197      _bytes = bytes;
1198    }
1199
1200    LittleEndianPackSegment(String JavaDoc name, int length, int bytes)
1201    {
1202      _name = name;
1203      _length = length;
1204      _bytes = bytes;
1205    }
1206    
1207    public int pack(Env env, BinaryBuilderValue bb, int i, Value []args)
1208      throws IOException JavaDoc
1209    {
1210      for (int j = 0; j < _length; j++) {
1211    Value arg;
1212
1213    if (i < args.length) {
1214      arg = args[i];
1215      i++;
1216    }
1217    else if (_length == Integer.MAX_VALUE)
1218      return i;
1219    else {
1220      env.warning("a: not enough arguments");
1221
1222      return i;
1223    }
1224 
1225    long v = arg.toLong();
1226
1227    for (int k = 0; k < _bytes; k++) {
1228      bb.appendByte((int) (v >> (8 * k)));
1229    }
1230      }
1231
1232      return i;
1233    }
1234    
1235    public void unpack(Env env, ArrayValue result, InputStream JavaDoc is)
1236      throws IOException JavaDoc
1237    {
1238      for (int j = 0; j < _length; j++) {
1239    Value key;
1240
1241    if (_name == "")
1242      key = LongValue.create(j);
1243    else if (_length == 1)
1244      key = new StringValueImpl(_name);
1245    else {
1246      StringBuilderValue sb = new StringBuilderValue();
1247      sb.append(_name);
1248      sb.append(j);
1249
1250      key = sb;
1251    }
1252    
1253    long v = 0;
1254
1255    for (int k = 0; k < _bytes; k++) {
1256      long d = is.read() & 0xff;
1257
1258      v |= d << 8 * k;
1259    }
1260
1261    result.put(key, LongValue.create(v));
1262      }
1263    }
1264  }
1265
1266  static class DoublePackSegment extends PackSegment {
1267    private final String JavaDoc _name;
1268    private final int _length;
1269
1270    DoublePackSegment(int length)
1271    {
1272      this("", length);
1273    }
1274
1275    DoublePackSegment(String JavaDoc name, int length)
1276    {
1277      _name = name;
1278      _length = length;
1279    }
1280    
1281    public int pack(Env env, BinaryBuilderValue bb, int i, Value []args)
1282      throws IOException JavaDoc
1283    {
1284      for (int j = 0; j < _length; j++) {
1285    Value arg;
1286
1287    if (i < args.length) {
1288      arg = args[i];
1289      i++;
1290    }
1291    else if (_length == Integer.MAX_VALUE)
1292      return i;
1293    else {
1294      env.warning("a: not enough arguments");
1295
1296      return i;
1297    }
1298 
1299    double d = arg.toDouble();
1300    long v = Double.doubleToLongBits(d);
1301
1302    for (int k = 7; k >= 0; k--) {
1303      bb.appendByte((int) (v >> (8 * k)));
1304    }
1305      }
1306
1307      return i;
1308    }
1309    
1310    public void unpack(Env env, ArrayValue result, InputStream JavaDoc is)
1311      throws IOException JavaDoc
1312    {
1313      for (int j = 0; j < _length; j++) {
1314    Value key;
1315
1316    if (_name == "")
1317      key = LongValue.create(j);
1318    else if (_length == 1)
1319      key = new StringValueImpl(_name);
1320    else {
1321      StringBuilderValue sb = new StringBuilderValue();
1322      sb.append(_name);
1323      sb.append(j);
1324
1325      key = sb;
1326    }
1327    
1328    long v = 0;
1329
1330    for (int k = 0; k < 8; k++) {
1331      long d = is.read() & 0xff;
1332
1333      v = 256 * v + d;
1334    }
1335
1336    result.put(key, new DoubleValue(Double.longBitsToDouble(v)));
1337      }
1338    }
1339  }
1340
1341  static class FloatPackSegment extends PackSegment {
1342    private final String JavaDoc _name;
1343    private final int _length;
1344
1345    FloatPackSegment(int length)
1346    {
1347      this("", length);
1348    }
1349
1350    FloatPackSegment(String JavaDoc name, int length)
1351    {
1352      _name = name;
1353      _length = length;
1354    }
1355    
1356    public int pack(Env env, BinaryBuilderValue bb, int i, Value []args)
1357      throws IOException JavaDoc
1358    {
1359      for (int j = 0; j < _length; j++) {
1360    Value arg;
1361
1362    if (i < args.length) {
1363      arg = args[i];
1364      i++;
1365    }
1366    else if (_length == Integer.MAX_VALUE)
1367      return i;
1368    else {
1369      env.warning("a: not enough arguments");
1370
1371      return i;
1372    }
1373 
1374    double d = arg.toDouble();
1375    int v = Float.floatToIntBits((float) d);
1376
1377    for (int k = 3; k >= 0; k--) {
1378      bb.appendByte((int) (v >> (8 * k)));
1379    }
1380      }
1381
1382      return i;
1383    }
1384    
1385    public void unpack(Env env, ArrayValue result, InputStream JavaDoc is)
1386      throws IOException JavaDoc
1387    {
1388      for (int j = 0; j < _length; j++) {
1389    Value key;
1390
1391    if (_name == "")
1392      key = LongValue.create(j);
1393    else if (_length == 1)
1394      key = new StringValueImpl(_name);
1395    else {
1396      StringBuilderValue sb = new StringBuilderValue();
1397      sb.append(_name);
1398      sb.append(j);
1399
1400      key = sb;
1401    }
1402    
1403    int v = 0;
1404
1405    for (int k = 0; k < 4; k++) {
1406      int d = is.read() & 0xff;
1407
1408      v = 256 * v + d;
1409    }
1410
1411    result.put(key, new DoubleValue(Float.intBitsToFloat(v)));
1412      }
1413    }
1414  }
1415
1416  static class NullPackSegment extends PackSegment {
1417    private final String JavaDoc _name;
1418    private final int _length;
1419
1420    NullPackSegment(int length)
1421    {
1422      this("", length);
1423    }
1424
1425    NullPackSegment(String JavaDoc name, int length)
1426    {
1427      _name = name;
1428      
1429      if (length == Integer.MAX_VALUE)
1430    length = 0;
1431      
1432      _length = length;
1433    }
1434    
1435    public int pack(Env env, BinaryBuilderValue bb, int i, Value []args)
1436      throws IOException JavaDoc
1437    {
1438      for (int j = 0; j < _length; j++) {
1439    bb.appendByte(0);
1440      }
1441
1442      return i;
1443    }
1444    
1445    public void unpack(Env env, ArrayValue result, InputStream JavaDoc is)
1446      throws IOException JavaDoc
1447    {
1448      for (int i = 0; i < _length; i++)
1449    is.read();
1450    }
1451  }
1452
1453  static class PositionPackSegment extends PackSegment {
1454    private final int _length;
1455
1456    PositionPackSegment(int length)
1457    {
1458      this("", length);
1459    }
1460
1461    PositionPackSegment(String JavaDoc name, int length)
1462    {
1463      if (length == Integer.MAX_VALUE)
1464    length = 0;
1465      
1466      _length = length;
1467    }
1468    
1469    public int pack(Env env, BinaryBuilderValue bb, int i, Value []args)
1470      throws IOException JavaDoc
1471    {
1472      while (bb.length() < _length) {
1473    bb.appendByte(0);
1474      }
1475
1476      return i;
1477    }
1478    
1479    public void unpack(Env env, ArrayValue result, InputStream JavaDoc is)
1480      throws IOException JavaDoc
1481    {
1482      throw new UnsupportedOperationException JavaDoc("'@' skip to position");
1483    }
1484  }
1485
1486  static int hexToDigit(Env env, char ch)
1487  {
1488    if ('0' <= ch && ch <= '9')
1489      return (ch - '0');
1490    else if ('a' <= ch && ch <= 'f')
1491      return (ch - 'a' + 10);
1492    else if ('A' <= ch && ch <= 'F')
1493      return (ch - 'A' + 10);
1494    else {
1495      env.warning("pack: non hex digit: " + (char) ch);
1496
1497      return 0;
1498    }
1499  }
1500
1501  static char digitToHex(int d)
1502  {
1503    d &= 0xf;
1504    
1505    if (d < 10)
1506      return (char) ('0' + d);
1507    else
1508      return (char) ('a' + d - 10);
1509  }
1510}
1511
Popular Tags