/[webpac]/openisis/current/org/openisis/PlainSerializer.java
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /openisis/current/org/openisis/PlainSerializer.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 237 - (hide annotations)
Mon Mar 8 17:43:12 2004 UTC (20 years, 2 months ago) by dpavlin
File size: 13278 byte(s)
initial import of openisis 0.9.0 vendor drop

1 dpavlin 237 /*
2     openisis - an open implementation of the CDS/ISIS database
3     Version 0.8.x (patchlevel see file Version)
4     Copyright (C) 2001-2003 by Erik Grziwotz, erik@openisis.org
5    
6     This library is free software; you can redistribute it and/or
7     modify it under the terms of the GNU Lesser General Public
8     License as published by the Free Software Foundation; either
9     version 2.1 of the License, or (at your option) any later version.
10    
11     This library is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14     Lesser General Public License for more details.
15    
16     You should have received a copy of the GNU Lesser General Public
17     License along with this library; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19    
20     see README for more information
21     EOH */
22    
23     package org.openisis;
24    
25     import java.io.*;
26     import java.net.Socket;
27     import java.util.ArrayList;
28    
29     /**
30     Serialization of fields by plain protocol.
31     <p>
32     $Id: PlainSerializer.java,v 1.8 2003/05/02 18:41:55 mawag Exp $
33     @version $Revision: 1.8 $
34     @author $Author: mawag $
35     */
36     public class PlainSerializer {
37    
38     private static class ProtocolViolation extends RuntimeException {
39     ProtocolViolation () {
40     super ();
41     }
42     ProtocolViolation (String msg) {
43     super (msg);
44     }
45     ProtocolViolation (byte arr[]) {
46     super ("got <" + new String (arr) + ">");
47     }
48     }
49    
50     private static class ByteBuf {
51     byte _b[];
52     int _cap, _pos;
53     ByteBuf (int cap) {
54     _b = new byte [_cap = cap];
55     _pos = 0;
56     }
57     void append (byte b[], int off, int len) {
58     if (0 < len) {
59     int np = _pos + len;
60     if (np > _cap) {
61     int nc = _cap;
62     while (np > (nc *= 2)) {
63     ;
64     }
65     byte nb[] = new byte [nc];
66     System.arraycopy (_b, 0, nb, 0, _pos);
67     _b = nb;
68     _cap = nc;
69     }
70     System.arraycopy (b, off, _b, _pos, len);
71     _pos = np;
72     }
73     }
74     }
75    
76     private static final byte[] NL = new byte [] { (byte)'\n' };
77     private static final byte[] HT = new byte [] { (byte)'\t' };
78     private static final byte[] VT = new byte [] { (byte)11 };
79    
80     private InputStream _in;
81     private OutputStream _out;
82     private String _enc = null;
83     private boolean _dbg = false;
84     private boolean _bin = false;
85    
86     private final void _write (byte[] arr, int off, int len) throws Exception {
87     if (_dbg) {
88     Log.verbose (this,
89     "w <" + new String (arr, off, len) + ">", null);
90     }
91     _out.write (arr, off, len);
92     }
93    
94     private final void _write (byte[] arr) throws Exception {
95     if (_dbg) {
96     Log.verbose (this,
97     "w <" + new String (arr, 0, arr.length) + ">", null);
98     }
99     _out.write (arr);
100     }
101    
102     private final int _read (byte[] arr) throws Exception {
103     int rd = _in.read (arr);
104     if (_dbg) {
105     Log.verbose (this,
106     "r <" + new String (arr, 0, rd) + ">", null);
107     }
108     return rd;
109     }
110    
111     /** write end of record to output stream.
112     @return success
113     */
114     public boolean flush () {
115     try {
116     _write (NL);
117     return true;
118     }
119     catch (Exception ex) {
120     Log.warn (this, "flush", ex);
121     }
122     return false;
123     }
124    
125     /** serialize one field.
126     @return success
127     */
128     public boolean write (Field fld) {
129     int j, lst;
130     byte[] bv;
131    
132     if (null == fld) {
133     return false;
134     }
135     try {
136     bv = Integer.toString (fld.tag).getBytes ();
137     _write (bv);
138     _write (HT);
139     if (null != fld.val && 0 < fld.val.length ()) {
140     bv = null != _enc ?
141     fld.val.getBytes (_enc) : fld.val.getBytes ();
142     lst = j = 0;
143     while (bv.length > j) {
144     if (NL[0] != bv[j]) {
145     ++j;
146     continue;
147     }
148     if (_bin) {
149     ++j;
150     _write (bv, lst, j - lst);
151     _write (HT);
152     }
153     else {
154     if (j > lst) {
155     _write (bv, lst, j - lst);
156     }
157     _write (VT);
158     ++j;
159     }
160     lst = j;
161     }
162     if (bv.length > lst) {
163     _write (bv, lst, bv.length - lst);
164     }
165     }
166     _write (NL);
167     return true;
168     }
169     catch (Exception ex) {
170     Log.warn (this, "serializing " + fld, ex);
171     }
172     return false;
173     }
174    
175     /** serialize fields.
176     @return success
177     */
178     public boolean write (Field[] flds) {
179     if (null == flds) {
180     return false;
181     }
182     for (int j = 0; flds.length > j; ++j) {
183     if (! write (flds[j])) {
184     return false;
185     }
186     }
187     return flush ();
188     }
189    
190     /** deserialize fields.
191     @return array of fields read from input stream, null on error
192     */
193     public Field[] read () {
194     byte[] rbuf = new byte [1024];
195     ByteBuf sbuf = new ByteBuf (1024);
196     ArrayList lst = new ArrayList ();
197     Field fld;
198     int rd, pos, tag, vs, val;
199     boolean rdt; // reading tag
200     boolean lnl; // last byte was NL
201     boolean neg; // tag negative
202     boolean bin = _bin;
203    
204     try {
205     tag = 0;
206     rdt = true;
207     neg = false;
208     lnl = false;
209     all:
210     while (true) {
211     rd = _read (rbuf);
212     if (0 >= rd) {
213     throw new ProtocolViolation ("no more bytes available");
214     }
215     vs = pos = 0;
216     while (pos < rd) {
217     if (rdt) {
218     if (HT[0] == rbuf[pos]) {
219     rdt = false;
220     vs = ++pos;
221     continue;
222     }
223     if (0 == tag && '-' == rbuf[pos]) {
224     neg = true;
225     ++pos;
226     continue;
227     }
228     val = rbuf[pos] - '0';
229     if (0 > val || 9 < val) {
230     if (0 == pos &&
231     NL[0] == rbuf[0] &&
232     0 == lst.size ()) {
233     Log.warn (this, null,
234     new ProtocolViolation ("empty response"));
235     break;
236     }
237     throw new ProtocolViolation (rbuf);
238     }
239     tag = 10 * tag + val;
240     ++pos;
241     continue;
242     }
243     if (lnl) {
244     lnl = false;
245     if (HT[0] == rbuf[pos]) {
246     bin = true;
247     sbuf.append (NL, 0, 1);
248     vs = ++pos;
249     continue;
250     }
251     fld = new Field (neg ? - tag : tag,
252     null == _enc ?
253     new String (sbuf._b, 0, sbuf._pos) :
254     new String (sbuf._b, 0, sbuf._pos, _enc)
255     );
256     lst.add (fld);
257     if (NL[0] == rbuf[pos]) {
258     if (pos != rd - 1) {
259     throw new ProtocolViolation ("trailing bytes");
260     }
261     break all;
262     }
263     sbuf._pos = 0;
264     rdt = true;
265     neg = false;
266     tag = 0;
267     continue;
268     }
269     if (VT[0] == rbuf[pos]) {
270     if (! bin) {
271     rbuf[pos] = NL[0];
272     }
273     }
274     else if (NL[0] == rbuf[pos]) {
275     if (pos > vs) {
276     sbuf.append (rbuf, vs, pos - vs);
277     }
278     lnl = true;
279     }
280     ++pos;
281     }
282     if (! rdt && rd > vs) {
283     sbuf.append (rbuf, vs, rd - vs);
284     }
285     }
286    
287     return (Field[]) lst.toArray (new Field [lst.size ()]);
288     }
289     catch (Exception ex) {
290     Log.warn (this, "read", ex);
291     }
292     return null;
293     }
294    
295     public void setBinaryMode (boolean bin) {
296     _bin = bin;
297     }
298    
299     /** Set character encoding to use in subsequent calls to
300     read and write.
301     @param enc if null, the platforms default encoding will be used
302     */
303     public void setEncoding (String enc) {
304     if (null != enc) {
305     try {
306     new String (NL, enc);
307     }
308     catch (UnsupportedEncodingException ex) {
309     Log.warn (this, "setEncoding(" + enc + ")", ex);
310     return;
311     }
312     }
313     _enc = enc;
314     }
315    
316     /** Constructor with read and write stream.
317     @param enc character encoding
318     @param bin binary mode
319     */
320     public PlainSerializer (
321     InputStream in, OutputStream out, String enc, boolean bin
322     ) {
323     _in = in;
324     _out = out;
325     setEncoding (enc);
326     setBinaryMode (bin);
327     Log.info (this, "ctor(" + enc + "," + bin + ")", null);
328     }
329    
330     /** Constructor using text mode and platforms default encoding.
331     */
332     public PlainSerializer (InputStream in, OutputStream out) {
333     this (in, out, null, false);
334     }
335    
336     /** Constructor for a socket connection to port@host.
337     @param enc character encoding
338     @param bin binary mode
339     @exception all exceptions a socket might throw
340     */
341     public PlainSerializer (
342     String hostname, int port, String enc, boolean bin
343     ) throws Exception {
344     try {
345     Socket sock = new Socket (hostname, port);
346     _in = sock.getInputStream ();
347     _out = sock.getOutputStream ();
348     setEncoding (enc);
349     setBinaryMode (bin);
350     Log.info (this, "ctor(" + hostname + ',' + port + "," +
351     enc + "," + bin + ")", null);
352     }
353     catch (Exception ex) {
354     Log.warn (this, "ctor(" + hostname + ',' + port + ")", ex);
355     throw ex;
356     }
357     }
358    
359     /** Constructor using text mode and platforms default encoding.
360     */
361     public PlainSerializer (String hostname, int port) throws Exception {
362     this (hostname, port, null, false);
363     }
364    
365     /** Close communication channels.
366     */
367     public void close () {
368     if (null != _in) {
369     try {
370     _in.close ();
371     }
372     catch (Exception ex) {
373     }
374     _in = null;
375     }
376     if (null != _out) {
377     try {
378     _out.close ();
379     }
380     catch (Exception ex) {
381     }
382     _out = null;
383     }
384     }
385    
386     // //////////////////////////////////////////////////////////////////////
387    
388     private class PSWriter extends Thread {
389     Field[] _rqs;
390     int _numr;
391     PSWriter (Field[] rqs, int numr) {
392     _rqs = rqs;
393     _numr = numr;
394     }
395     public void run () {
396     for (int j = 0; _numr > j; ++j) {
397     if (! write (_rqs)) {
398     Log.warn (null, "error writing rqs #" + j, null);
399     System.exit (1);
400     }
401     try {
402     synchronized (PSWriter.this) {
403     PSWriter.this.wait ();
404     }
405     }
406     catch (Exception ex) {
407     Log.warn (PSWriter.this, "wait", ex);
408     }
409     }
410     }
411     }
412    
413     /** Tester:<br/><pre>
414     java org.openisis.PlainSerializer -p
415     java org.openisis.PlainSerializer -b -p
416     java org.openisis.PlainSerializer -e UTF-8 -p
417     java org.openisis.PlainSerializer -e UTF-8 -b -p
418     java org.openisis.PlainSerializer -e UTF-16 -p
419     java org.openisis.PlainSerializer -e UTF-16 -b -p
420     java org.openisis.PlainSerializer -p 55
421     java org.openisis.PlainSerializer -b -p 55
422     java org.openisis.PlainSerializer -e UTF-16 -p 55
423     java org.openisis.PlainSerializer -e UTF-16 -b -p 55
424     </pre>
425     */
426     public static void main (String argv[]) {
427     try {
428     String novel = "blah";
429     String host = "localhost";
430     String enc = null;
431     int port = 8080;
432     int numr = 1;
433     boolean pipe = false;
434     boolean dbg = false;
435     boolean bin = false;
436     int j = 0;
437     int len = argv.length;
438    
439     for (int jj = 0; argv.length > jj; ++jj) {
440     if (argv[jj].startsWith ("-d")) {
441     dbg = true;
442     ++j;
443     --len;
444     continue;
445     }
446     if (argv[jj].startsWith ("-b")) {
447     bin = true;
448     ++j;
449     --len;
450     continue;
451     }
452     if (argv[jj].startsWith ("-e")) {
453     enc = argv[++jj];
454     j += 2;
455     len -= 2;
456     continue;
457     }
458     break;
459     }
460     switch (len) {
461     case 3:
462     numr = Integer.parseInt (argv[2 + j]);
463     case 2:
464     if (argv[j].startsWith ("-p")) {
465     pipe = true;
466     numr = Integer.parseInt (argv[1 + j]);
467     break;
468     }
469     port = Integer.parseInt (argv[1 + j]);
470     case 1:
471     if (argv[j].startsWith ("-p")) {
472     pipe = true;
473     }
474     else {
475     host = argv[j];
476     }
477     case 0:
478     break;
479     default:
480     throw new IllegalArgumentException ();
481     }
482    
483     PlainSerializer ps;
484     if (pipe) {
485     PipedInputStream pi = new PipedInputStream ();
486     PipedOutputStream po = new PipedOutputStream (pi);
487     ps = new PlainSerializer (pi, po, enc, bin);
488     }
489     else {
490     ps = new PlainSerializer (host, port, enc, bin);
491     }
492     ps._dbg = dbg;
493     for (j = 0; 8 > j; ++j) {
494     novel = novel + novel;
495     }
496     String[] vals = new String [] {
497     "localhorst",
498     "nothing",
499     "one",
500     null,
501     "",
502     novel,
503     "\nfive\nfire\t",
504     "\t\n\t\n" + (bin ? new String (VT) : ""),
505     "seven",
506     "\n"
507     };
508     Field[] rqs = new Field [] {
509     new Field (-2, vals[0]),
510     new Field (0, vals[1]),
511     new Field (1, vals[2]),
512     new Field (2, vals[3]),
513     new Field (3, vals[4]),
514     new Field (4, vals[5]),
515     new Field (5, vals[6]),
516     new Field (6, vals[7]),
517     new Field (7, vals[8]),
518     new Field (8, vals[9])
519     };
520     int k, kk;
521     Field[] rsp;
522     PSWriter writer = ps.new PSWriter (rqs, numr);
523     writer.start ();
524    
525     for (j = 0; numr > j; ++j) {
526     rsp = ps.read ();
527     if (null == rsp) {
528     Log.warn (null, "error reading rsp #" + j, null);
529     System.exit (1);
530     }
531     for (k = kk = 0; rsp.length > k; ++k) {
532     if (0 > rsp[k].tag) {
533     if (kk >= rqs.length || ! rsp[k].equals (rqs[kk])) {
534     // skip additional server fields
535     if (dbg) {
536     Log.verbose (null, "skipping server field " +
537     rsp[k] + " ...", null);
538     }
539     continue;
540     }
541     }
542     if (rqs.length <= kk) {
543     for (kk = 0; rsp.length > kk; ++kk) {
544     Log.verbose (new Integer (kk),
545     rsp[kk].toString (), null);
546     }
547     Log.warn (null,
548     "length mismatch rsp #" + j + ": " + k + "/" +
549     kk + "/" + rsp.length + ">=" + rqs.length,
550     null);
551     System.exit (1);
552     }
553     if (! rsp[k].equals (rqs[kk])) {
554     Log.warn (null, "field #" + k + " rqs #" + j +
555     " differs: <" + rsp[k] + "> != <" + rqs[kk] +
556     ">", null);
557     System.exit (1);
558     }
559     ++kk;
560     }
561     if (0 != j && 0 == (j % 100)) {
562     System.out.println (j + " ...");
563     }
564     synchronized (writer) {
565     writer.notify ();
566     }
567     }
568     ps.close ();
569    
570     System.out.println ("ok.");
571     }
572     catch (Exception ex) {
573     ex.printStackTrace (System.err);
574     System.err.println ("usage: " + PlainSerializer.class.getName () +
575     " [-b(inary)] [-d(ebug)] [-e(ncoding) <name>]" +
576     " [<hostname=\"localhost\"> [<port> [<numrequests>]]] |" +
577     " -p(ipe) [<numrequests>]");
578     System.exit (1);
579     }
580     }
581     }
582    

  ViewVC Help
Powered by ViewVC 1.1.26