00001 /****************************************************************************** 00002 00003 @mainpage The Mango Tree 00004 00005 Mango is a collection of D packages with an orientation toward 00006 server-side programming. These packages may be used together 00007 or in isolation and, in many cases, can be just as applicable 00008 to client-side development. Mango is targeted for Win32 and 00009 linux platforms. 00010 00011 There are currently eight packages under the Mango Tree: 00012 00013 @li mango.io: a high-performance buffered IO package. Primary 00014 functionality includes memory Buffers, external Conduits 00015 (files, sockets, etc), file-system manipulation, several 00016 flavors of Readers and Writers (formatted data), TextFormat 00017 (printf) and TextLayout support, class serialization, 00018 tokenization, and a whole lot more. Socket support is via 00019 the gracious provision of Christopher Miller's socket module. 00020 See FilePath, FileProxy, FileConduit, FileSystem, SocketConduit, 00021 ServerSocket, MulticastSocket, SocketListener, Token, Stdin, 00022 Stdout, Reader, Writer, IPickle and PickleRegistry. 00023 00024 @li mango.http.client: An HTTP client for conversing with a remote 00025 HTTP server. Supports headers, query parameters, cookies, 00026 timeout etc. Tokenizer classes in mango.io are handy for 00027 parsing returned content. See HttpClient. 00028 00029 @li mango.http.server: an HTTP server framework is provided for 00030 implementing a variety of high performance servers based 00031 on the HTTP protocol. This is not a fully-fledged v1.1 00032 implementation. That is, it doesn't currently support 00033 'fields' or 'keep alive'. However, it happily processes 00034 each request without allocating memory, making it unusually 00035 efficient. This is an example of how D array-slicing can 00036 seriously improve runtime efficiency. An open-source HTTPS 00037 library should be fairly easy to bolt in. Modules HttpServer 00038 and IProvider are the primary entry points: you implement an 00039 instance of the latter, and hand it to the former. 00040 00041 @li mango.servlet: A servlet-style engine that sits upon 00042 mango.server. Includes most of the things that Java servlet 00043 programmers would expect, and attempts to improve in certain 00044 key areas such as the IO system. See Servlet and ServletProvider. 00045 00046 @li mango.cache: Some simple caching mechanisms. Includes MRU 00047 caching via a queue, and level-two caching (to disk) via 00048 class-serialization. Now based upon a derivative of Doug Lea's 00049 concurrent hashmap. The mango.cluster package derives from 00050 mango.cache, so it's really easy to switch between a local 00051 cache implementation and a clustered version. See ICache, 00052 IMutableCache, PlainCache, QueuedCache and VirtualCache. 00053 00054 @li mango.log: A port of the wildly popular Log4J package, for 00055 logging and tracing of runtime behaviour. See 00056 <A HREF="http://logging.apache.org/log4j/docs/documentation.html">this page</A> 00057 for an introduction to Log4J. Mango.log exposes an extensible and 00058 customizable framework, has been optimised heavily for 00059 minimal runtime overhead, does not impact the GC once 00060 initialised, and operates with either Mango.io or Phobos. 00061 Mango.log can generate remote log messages for use with Chainsaw, 00062 and has a browser-based 'Administrator' which allows remote, 00063 dynamic inspection and adjustment of the log settings within an 00064 executing program. See Logger, BasicConfigurator and 00065 PropertyConfigurator. There are a number of examples that show 00066 how to use these facilities (e.g Servlets.d) 00067 00068 @li mango.cluster: A clustering package for servers and other 00069 network aware applications. Currently supports clustered 00070 caching and queuing, where the former is limited to a fixed 00071 MRU number of entries per node, and the latter is limited to an 00072 upper memory waterline. While the underlying QOS (quality of 00073 service) substrate is setup to be plugable, the QOS 00074 currently provided is stream/multicast based. Note that this 00075 package is not a substitute for a persistence layer; instead 00076 it is a tool for enabling horizontal scaling within a system 00077 that has been designed explicitly from the outset to scale. 00078 On the other hand, it can significantly enhance the throughput 00079 of any persistence layer by offloading a large percentage of 00080 read operations. See CacheInvalidatee, CacheInvalidator, 00081 NetworkCombo, NetworkAlert, NetworkCache and NetworkQueue. 00082 00083 @li mango.icu: Set of wrappers around the ICU I18N project. See 00084 <A HREF="http://oss.software.ibm.com/icu/">this page</A> for 00085 the scoop on what is probably the most comprehensive and 00086 functional project in this particular arena. Mango.icu exposes 00087 the C API in a manner that takes advantage of D arrays and 00088 so on. See UCalendar, UChar, UConverter, UDateFormat, ULocale, 00089 UMessageFormat, UNumberFormat, UResourceBundle, UString, 00090 UText, UCollator, USet, UTransform, USearch, UNormalize, 00091 UDomainName, UBreakIterator, and UTimeZone. 00092 Numeric formatting is handled by a range of subclasses, 00093 including UDecimalFormat, UCurrencyFormat, UPercentFormat, 00094 UScientificFormat, and USpelloutFormat. 00095 There is set of adapter classes in UMango which can be used 00096 to bind the ICU converters to Mango.io, thereby enabling 00097 Reader and Writer with the full suite of unicode transcoders. 00098 00099 Package dependencies are as follows (from left to right): 00100 00101 @code 00102 mango.io => phobos (minimal) 00103 mango.log => mango.io (without -version=Isolated) 00104 mango.icu => mango.io (without -version=Isolated) 00105 mango.cache => mango.io 00106 mango.http.server => mango.io 00107 mango.http.client => mango.io, mango.server 00108 mango.cluster => mango.io, mango.cache, mango.log 00109 mango.servlet => mango.io, mango.http.server, mango.cache, mango.log 00110 @endcode 00111 00112 Mango.icu and Mango.log are also made available as independent packages, 00113 outside of the regular Mango Tree. To enable this, specify the flag 00114 -version=Isolated when building those packages 00115 00116 You might take a look at the unittest.d source to get a general 00117 feel for functionality, and browse the various pdf files 00118 <A HREF="http://svn.dsource.org/svn/projects/mango/trunk/doc/">here</A> 00119 along with the class-hierarchy or alphabetical-list linked at the 00120 top of this page. There's also a set of examples 00121 <A HREF="http://svn.dsource.org/svn/projects/mango/trunk/example/">over here</A>. 00122 Those will probably be sufficient to get an idea where the Mango Tree 00123 might come in handy within your projects. 00124 00125 Discussion forums are hosted 00126 <A HREF="http://www.dsource.org/forums/viewforum.php?f=5">here</A>, 00127 and the general introduction starts 00128 <A HREF="http://www.dsource.org/forums/viewtopic.php?t=148">here</A>. 00129 00130 *******************************************************************************/ 00131 00132 00133 00134 00135 /****************************************************************************** 00136 00137 @file unittest.d 00138 00139 Test jig for the mango.io package. 00140 00141 00142 This shows a number of different ways to manipulate buffers, 00143 readers, writers, and how to perform IO on files and sockets. 00144 00145 The basic premise behind this IO package is as follows: 00146 00147 1) the central concept is that of a buffer. The buffer acts 00148 as a queue (line) where items are removed from the front 00149 and new items are added to the back. Buffers are modeled 00150 by mango.io.model.IBuffer, and a concrete implementation 00151 is provided via mango.io.Buffer. 00152 00153 2) buffers can be written to directly, but a Reader and/or 00154 Writer are typically used to read & write formatted data. 00155 These readers & writers are bound to a specific buffer; 00156 often the same buffer. It's also perfectly legitimate to 00157 bind multiple writers to the same buffer; they will all 00158 behave serially as one would expect. The same applies to 00159 multiple readers on the same buffer. Readers and writers 00160 support two styles of IO: put/get, and the C++ style << 00161 and >> operators. All such operations can be chained. 00162 00163 3) Any class can be made compatable with the reader/writer 00164 framework by implementing the IReadable and/or IWritable 00165 interfaces. Each of these specify just a single method. 00166 00167 4) Buffers may also be tokenized. This is handy when one is 00168 dealing with text input, and/or the content suits a more 00169 fluid format than most typical readers & writers support. 00170 Tokens are mapped directly onto buffer content, so there 00171 is only minor overhead in using them. Tokens can be read 00172 and written by reader/writers also, using a more relaxed 00173 set of rules than those applied to integral IO. 00174 00175 5) buffers are sometimes memory-only, in which case there 00176 is nothing left to do when a reader (or tokenizer) hits 00177 end of buffer conditions. Other buffers are themselves 00178 bound to a Conduit. When this is the case, a reader will 00179 eventually cause the buffer to reload via its associated 00180 conduit. Previous buffer content will thus be lost. The 00181 same concept is applied to writers, whereby they flush 00182 the content of a full buffer to a bound conduit before 00183 continuing. 00184 00185 6) conduits provide virtualized access to external content, 00186 and represent things like files or Internet connections. 00187 They are just a different kind of stream. Conduits are 00188 modelled by mango.io.model.IConduit, and implemented via 00189 classes FileConduit and SocketConduit. Additional kinds 00190 of conduit are easy to construct: one either subclasses 00191 mango.io.Conduit, or implements mango.io.model.IConduit. 00192 The conduit reads and writes a buffer in large segments; 00193 typically the entire buffer. 00194 00195 7) additional file-system support is provided through two 00196 classes: FileSystem supports operations such as getting 00197 and setting the current directory, and FileProxy exposes 00198 facilities to manipulate both files and directories. 00199 00200 8) console IO is implemented via Stdio, using FileConduit 00201 and appropriate readers and writers. Console IO can be 00202 redirected in the traditional (shell) manner. 00203 00204 9) the package is intended to be portable between linux and 00205 Win32 platforms. 00206 00207 00208 Kris Bell, March 26th 2004 00209 00210 *******************************************************************************/ 00211 00212 00213 // test these modules 00214 import mango.io.Uri, 00215 mango.io.Utf, 00216 mango.io.Stdin, 00217 mango.io.Stdout, 00218 mango.io.Token, 00219 mango.io.Reader, 00220 mango.io.Writer, 00221 mango.io.Buffer, 00222 mango.io.Socket, 00223 mango.io.Conduit, 00224 mango.io.FilePath, 00225 mango.io.FileStyle, 00226 mango.io.FileProxy, 00227 mango.io.Tokenizer, 00228 mango.io.TextReader, 00229 mango.io.TextWriter, 00230 mango.io.FileBucket, 00231 mango.io.FileConduit, 00232 mango.io.TextLayout, 00233 mango.io.TextFormat, 00234 mango.io.ColumnWriter, 00235 mango.io.DisplayWriter, 00236 mango.io.PickleReader, 00237 mango.io.PickleWriter, 00238 mango.io.SocketConduit, 00239 mango.io.SocketListener, 00240 mango.io.ArrayAllocator, 00241 mango.io.PickleRegistry, 00242 mango.io.DatagramSocket, 00243 mango.io.MulticastSocket; 00244 00245 // need this for logging 00246 import mango.log.Logger, 00247 mango.log.Layout, 00248 mango.log.Manager, 00249 mango.log.XmlLayout, 00250 mango.log.DateLayout, 00251 mango.log.Configurator, 00252 mango.log.FileAppender, 00253 mango.log.ConsoleAppender, 00254 mango.log.RollingFileAppender; 00255 00256 // need these for reading & writing classes 00257 import mango.io.model.IReader, 00258 mango.io.model.IWriter, 00259 mango.io.model.IPickle; 00260 00261 // add a bunch of stuff for testing the http server 00262 import mango.http.server.HttpParams, 00263 mango.http.server.HttpCookies, 00264 mango.http.server.HttpHeaders, 00265 mango.http.server.HttpServer, 00266 mango.http.server.HttpRequest, 00267 mango.http.server.HttpResponse, 00268 mango.http.server.HttpProvider; 00269 00270 import mango.http.server.model.IProvider, 00271 mango.http.server.model.IProviderBridge; 00272 00273 import mango.http.client.HttpClient; 00274 00275 import mango.servlet.Servlet, 00276 mango.servlet.ServletConfig, 00277 mango.servlet.ServletContext, 00278 mango.servlet.ServletProvider; 00279 00280 import mango.cache.PlainCache, 00281 mango.cache.HashMap, 00282 mango.cache.Payload, 00283 mango.cache.QueuedCache, 00284 mango.cache.VirtualCache; 00285 00286 import mango.cluster.Message, 00287 mango.cluster.NetworkQueue, 00288 mango.cluster.NetworkCache, 00289 mango.cluster.CacheInvalidator, 00290 mango.cluster.CacheInvalidatee; 00291 00292 import mango.cluster.qos.socket.Cluster, 00293 mango.cluster.qos.socket.ClusterServer, 00294 mango.cluster.qos.socket.ProtocolReader, 00295 mango.cluster.qos.socket.ProtocolWriter; 00296 00297 import mango.icu.UMango, 00298 mango.icu.URegex, 00299 mango.icu.UString, 00300 mango.icu.UDomainName, 00301 mango.icu.UStringPrep, 00302 mango.icu.UConverter, 00303 mango.icu.USet, 00304 mango.icu.UCollator, 00305 mango.icu.UTimeZone, 00306 mango.icu.UEnumeration, 00307 mango.icu.UMessageFormat; 00308 00309 import mango.format.Double; 00310 00311 import mango.time.Rfc1123; 00312 00313 import mango.sys.Epoch; 00314 00315 //import mango.xml.dom.all; 00316 00317 /******************************************************************************* 00318 00319 Directive for build.exe to include the winsock2 library 00320 00321 *******************************************************************************/ 00322 00323 version (build) 00324 { 00325 version (Win32) 00326 pragma (link, wsock32); 00327 } 00328 00329 /******************************************************************************* 00330 00331 global scope variables 00332 00333 *******************************************************************************/ 00334 00335 private Logger logger; 00336 00337 /******************************************************************************* 00338 00339 Simple test of in-memory buffer. Bind both a Reader and a Writer 00340 onto the same buffer. 00341 00342 *******************************************************************************/ 00343 00344 static void testBuffer() 00345 { 00346 // create a small heap buffer 00347 Buffer buf = new Buffer (256); 00348 00349 // map same buffer into both reader and writer 00350 Writer w = new Writer (buf); 00351 Reader r = new Reader (buf); 00352 00353 int i = 10; 00354 int j = 20; 00355 double d = 3.14159; 00356 char[] c = "testing"; 00357 00358 // write integral types out 00359 w (c) (i) (j) (d); 00360 00361 // read them back again 00362 r (c) (i) (j) (d); 00363 00364 assert(i==10); 00365 assert(j==20); 00366 assert(d==3.14159); 00367 assert(c=="testing"); 00368 00369 // reset 00370 buf.clear(); 00371 00372 // same thing again, but using iostream syntax instead 00373 w << c << i << j << d; 00374 00375 // read them back again 00376 r >> c >> i >> j >> d; 00377 00378 assert(i==10); 00379 assert(j==20); 00380 assert(d==3.14159); 00381 assert(c=="testing"); 00382 00383 // reset 00384 buf.clear(); 00385 00386 // same thing again, but using put() syntax instead (and swap i & j) 00387 w.put(c).put(i).put(j).put(d); 00388 r.get(c).get(j).get(i).get(d); 00389 00390 assert(i==20); 00391 assert(j==10); 00392 assert(d==3.14159); 00393 assert(c=="testing"); 00394 } 00395 00396 00397 /******************************************************************************* 00398 00399 Append to a buffer directly without using a Writer. This can be 00400 useful for appending a set of strings (or other array type) to 00401 a contiguous space in a similar fashion to std.outbuffer. 00402 00403 *******************************************************************************/ 00404 00405 static void testAppend() 00406 { 00407 char[] foo = "to write some D code"; 00408 00409 // create a small heap buffer 00410 Buffer buf = new Buffer (256); 00411 00412 // append some text directly to it 00413 buf.append ("now is the time for all good men ").append(foo); 00414 00415 // output the combined string 00416 Stdout (buf.toString) (CR); 00417 } 00418 00419 00420 /******************************************************************************* 00421 00422 write delimited text tokens to a buffer, then read them back out 00423 to the console 00424 00425 *******************************************************************************/ 00426 00427 static void testToken1() 00428 { 00429 // create a small buffer on top of a static array 00430 static ubyte[128] storage; 00431 Buffer buf = new Buffer (storage); 00432 00433 // write tokens with a comma between each 00434 IWriter write = new TextWriter (buf, ","); 00435 00436 // bind a comma-tokenizer to a token instance 00437 BoundToken token = new BoundToken (Tokenizers.comma); 00438 00439 // write some stuff to the buffer 00440 write ("now is the time for all good men") (3.14159); 00441 00442 // read it back, and display as text 00443 while (token.next (buf)) 00444 Stdout (token) (CR); 00445 } 00446 00447 /******************************************************************************* 00448 00449 Use tokens directly with reader/writer also 00450 00451 *******************************************************************************/ 00452 00453 static void testToken2() 00454 { 00455 // create a small buffer on the heap 00456 Buffer buf = new Buffer (256); 00457 00458 // write items with a comma between each 00459 IWriter write = new TextWriter (buf, ","); 00460 00461 // write some stuff to the buffer 00462 write ("now is the time for all good men") (3.14159); 00463 00464 // bind a couple of tokens to a comma tokenizer 00465 ReaderToken text = new ReaderToken (Tokenizers.comma); 00466 ReaderToken number = new ReaderToken (Tokenizers.comma); 00467 00468 // create any old reader since we only use it for handling tokens 00469 IReader read = new Reader (buf); 00470 00471 // populate both tokens via reader 00472 read (text) (number); 00473 00474 // print them to the console 00475 Stdout (text) (':') (number) (CR); 00476 } 00477 00478 /******************************************************************************* 00479 00480 use TextReader to convert text into integral types. This is akin 00481 to what scanf does. 00482 00483 *******************************************************************************/ 00484 00485 static void testToken3() 00486 { 00487 // create a small buffer 00488 Buffer buf = new Buffer (256); 00489 00490 // write tokens with a comma between each 00491 TextWriter write = new TextWriter (buf, ","); 00492 00493 // write some stuff to the buffer 00494 write (101) (3.14159); 00495 00496 // map a comma-tokenizing reader onto our buffer 00497 TextReader read = new TextReader (buf, Tokenizers.comma); 00498 00499 real pi; 00500 int integer; 00501 00502 // convert both tokens via reader 00503 read (integer) (pi); 00504 00505 // print them to the console 00506 Stdout (integer) (',') (pi) (CR); 00507 } 00508 00509 00510 /******************************************************************************* 00511 00512 Read line tokens via a TextReader 00513 00514 *******************************************************************************/ 00515 00516 static void testToken4() 00517 { 00518 // open a file for reading 00519 FileConduit fc = new FileConduit ("test.txt"); 00520 00521 // create a buffer for transferring content 00522 IBuffer buffer = fc.createBuffer (); 00523 00524 // map a line-tokenizing reader onto our buffer 00525 TextReader read = new TextReader (buffer, Tokenizers.line); 00526 00527 char[] ca; 00528 00529 // read a line of text 00530 read (ca); 00531 00532 // display it on the console 00533 Stdout (ca) (CR); 00534 } 00535 00536 00537 00538 /******************************************************************************* 00539 00540 Use printf via a wrapper class 00541 00542 *******************************************************************************/ 00543 00544 static void testFormat() 00545 { 00546 // create a Format instance 00547 TextFormat format = new TextFormat (256); 00548 00549 // write text to Stdout 00550 Stdout (format ("there are %d arguments to every %s", 3, "contradiction")) (CR); 00551 } 00552 00553 00554 /******************************************************************************* 00555 00556 Layout text strings in an indexed fashion 00557 00558 *******************************************************************************/ 00559 00560 static void testLayout() 00561 { 00562 // create a Layout instance 00563 LayoutChar layout = new LayoutChar (256); 00564 00565 // write text to Stdout 00566 Stdout (layout ("%2 %1", "one", "two")) (CR); 00567 } 00568 00569 00570 /******************************************************************************* 00571 00572 Use interfaces to make any class reader and/or writer compatible 00573 00574 *******************************************************************************/ 00575 00576 static void testClassIO() 00577 { 00578 // define a readable/writable class (via interfaces) 00579 class Foo : IReadable, IWritable 00580 { 00581 private int x = 11; 00582 private int y = 112; 00583 00584 void write (IWriter put) 00585 { 00586 put (x) (y); 00587 } 00588 00589 void read (IReader get) 00590 { 00591 get (x) (y); 00592 } 00593 } 00594 00595 // create a small heap buffer 00596 Buffer buf = new Buffer (256); 00597 00598 // map reader/writer onto same buffer 00599 Writer write = new Writer (buf); 00600 Reader read = new Reader (buf); 00601 00602 // construct a Foo 00603 Foo foo = new Foo(); 00604 00605 // write it 00606 write (foo); 00607 00608 // read it back 00609 read (foo); 00610 } 00611 00612 00613 /******************************************************************************* 00614 00615 Use interfaces to make any class serializable. This will be used 00616 by mango.server to move class-instances around the network. Each 00617 class is effectively a factory for itself. 00618 00619 Note that this is not the same as Java; you can't ship code with 00620 the data ... one might perhaps use dll's or something to do that. 00621 00622 *******************************************************************************/ 00623 00624 static void testClassSerialization() 00625 { 00626 // define a serializable class (via interfaces) 00627 class Bar : IPickle, IPickleFactory 00628 { 00629 private int x = 11; 00630 private int y = 112; 00631 00632 void write (IWriter write) 00633 { 00634 write (x) (y); 00635 } 00636 00637 void read (IReader read) 00638 { 00639 read (x) (y); 00640 assert (x == 11 && y == 112); 00641 } 00642 00643 Object create (IReader reader) 00644 { 00645 Bar bar = new Bar (); 00646 bar.read (reader); 00647 return bar; 00648 } 00649 00650 char[] getGuid () 00651 { 00652 return "unittest.Bar"; 00653 } 00654 } 00655 00656 static Object create (IReader reader) 00657 { 00658 Bar bar = new Bar(); 00659 bar.read (reader); 00660 return bar; 00661 } 00662 00663 // setup for serialization 00664 Buffer buf = new Buffer (256); 00665 PickleWriter w = new PickleWriter (buf); 00666 PickleReader r = new PickleReader (buf); 00667 00668 r.setAllocator (new BufferAllocator); 00669 00670 // construct a Bar 00671 Bar bar = new Bar (); 00672 00673 // tell registry about this object 00674 //PickleRegistry.enroll (&create, "unittest.Bar"); 00675 PickleRegistry.enroll (bar); 00676 00677 // serialize it 00678 w.freeze (bar); 00679 00680 // create a new instance and populate. This just shows the basic 00681 // concept, not a fully operational implementation 00682 Object o = r.thaw (); 00683 } 00684 00685 00686 /******************************************************************************* 00687 00688 open a file, and stream directly to console 00689 00690 *******************************************************************************/ 00691 00692 static void testFile4() 00693 { 00694 // open a file for reading 00695 FileConduit fc = new FileConduit ("test.txt"); 00696 00697 // stream directly to console 00698 Stdout.conduit.copy (fc); 00699 } 00700 00701 00702 /******************************************************************************* 00703 00704 Create a file for random access. Write some stuff to it, rewind to 00705 file start and read back. 00706 00707 *******************************************************************************/ 00708 00709 static void testRandomAccess() 00710 { 00711 // open a file for reading 00712 auto FileConduit fc = new FileConduit ("random.bin", FileStyle.ReadWriteCreate); 00713 00714 // construct (binary) reader & writer upon this conduit 00715 Reader read = new Reader(fc); 00716 Writer write = new Writer(fc); 00717 00718 int x=10, y=20; 00719 00720 // write some data 00721 write (x) (y); 00722 00723 // flush output since IO is buffered 00724 write (); 00725 00726 // rewind to file start 00727 fc.seek (0); 00728 00729 // read data back again, but swap destinations 00730 read (y) (x); 00731 00732 assert (y==10); 00733 assert (x==20); 00734 } 00735 00736 00737 /******************************************************************************* 00738 00739 Create a file for random access. Write some stuff to it, rewind to 00740 file start and read back. 00741 00742 *******************************************************************************/ 00743 00744 static void testConduitFilters() 00745 { 00746 class MyFilter1 : ConduitSource 00747 { 00748 int read (void[] dst) 00749 { 00750 Stdout.print ("filtering input ...\n"); 00751 return next.read (dst); 00752 } 00753 } 00754 00755 class MyFilter2 : ConduitSink 00756 { 00757 int write (void[] src) 00758 { 00759 Stdout.print ("filtering output ...\n"); 00760 return next.write (src); 00761 } 00762 } 00763 00764 // open a file for reading 00765 auto FileConduit fc = new FileConduit ("random.bin", FileStyle.ReadWriteCreate); 00766 fc.attach (new MyFilter2); 00767 fc.attach (new MyFilter1); 00768 fc.attach (new MyFilter1); 00769 00770 // construct (binary) reader & writer upon this conduit 00771 Reader read = new Reader(fc); 00772 Writer write = new Writer(fc); 00773 00774 int x=1; 00775 00776 // write some data, and flush it 00777 write (x) (); 00778 00779 // rewind to file start 00780 fc.seek (0); 00781 00782 // read data back again 00783 read (x); 00784 } 00785 00786 00787 /******************************************************************************* 00788 00789 open a file, and explicitly buffer it to another conduit. This is 00790 effectively what Conduit.copyTo() does. 00791 00792 *******************************************************************************/ 00793 00794 static void testFile5() 00795 { 00796 // open a file for reading 00797 FileConduit fc = new FileConduit ("test.txt"); 00798 00799 // create a buffer for transferring content 00800 IBuffer buffer = fc.createBuffer (); 00801 00802 // stream the data from file to stdout. This is probably as fast as 00803 // one can practically make operations of this type. 00804 while (fc.read (buffer) != fc.Eof) 00805 Stdout.conduit.write (buffer); 00806 00807 // ensure the writer actually wrote everything 00808 buffer.flush(); 00809 } 00810 00811 00812 /******************************************************************************* 00813 00814 Open a file and read it line-by-line using a line tokenizer. This 00815 uses CompositeToken to hide some of the details. 00816 00817 *******************************************************************************/ 00818 00819 static void testFile1() 00820 { 00821 // open a file for reading 00822 FileConduit fc = new FileConduit ("test.txt"); 00823 00824 // create a Token and bind it to both the file and a line-tokenizer 00825 CompositeToken line = new CompositeToken (Tokenizers.line, fc); 00826 00827 // read file a line at a time. Method next() returns false when no more 00828 // delimiters are found. Note there may be an unterminated line at eof 00829 while (line.get) 00830 Stdout (line) (CR); 00831 } 00832 00833 00834 /******************************************************************************* 00835 00836 Unwound version of above: we now explicitly pass a buffer instance 00837 to the tokenizer, although the token itself is still bound. 00838 00839 *******************************************************************************/ 00840 00841 static void testFile2() 00842 { 00843 // open a file for reading 00844 FileConduit fc = new FileConduit ("test.txt"); 00845 00846 // create a buffer for reading the file 00847 IBuffer buffer = fc.createBuffer(); 00848 00849 // bind a line-tokenizer to our input token 00850 BoundToken line = new BoundToken (Tokenizers.line); 00851 00852 // read file a line at a time. Method next() returns false when no more 00853 // delimiters are found. Note there may be an unterminated line at eof 00854 while (line.next(buffer) || line.getLength()) 00855 Stdout (line) (CR); 00856 } 00857 00858 00859 /******************************************************************************* 00860 00861 Further unwinding of above: we invoke the tokenizer directly, 00862 explicitly passing both the buffer and the token 00863 00864 *******************************************************************************/ 00865 00866 static void testFile3() 00867 { 00868 // open a file for reading 00869 FileConduit fc = new FileConduit ("test.txt"); 00870 00871 // create a buffer for reading the file 00872 IBuffer buffer = fc.createBuffer(); 00873 00874 // create a token for receiving the line 00875 Token token = new Token (); 00876 00877 // read file a line at a time. Method next() returns false when no more 00878 // delimiters are found. Note there may be an unterminated line at eof 00879 while (Tokenizers.line.next(buffer, token) || token.getLength()) 00880 Stdout.put(token).cr(); 00881 } 00882 00883 00884 /******************************************************************************* 00885 00886 Recursively scan files and directories, adding filtered files to 00887 an output structure as we go. Thanks to Chris S for this. 00888 00889 *******************************************************************************/ 00890 00891 void testScanFiles() 00892 { 00893 /*********************************************************************** 00894 00895 ***********************************************************************/ 00896 00897 struct Dependencies 00898 { 00899 FileProxy[] mods; 00900 FilePath[] pkgs; 00901 } 00902 00903 /*********************************************************************** 00904 00905 ***********************************************************************/ 00906 00907 void scanFiles (inout Dependencies deps, FilePath base) 00908 { 00909 /*************************************************************** 00910 00911 delegate for filtering sub-directories and 00912 D source files 00913 00914 ***************************************************************/ 00915 00916 bit filter (FilePath fp) 00917 { 00918 char[] sbuf = fp.getExtension(); 00919 00920 if (fp.getName[0] != '.') 00921 if (sbuf.length == 0 || sbuf == "d") 00922 return true; 00923 00924 return false; 00925 } 00926 00927 /*************************************************************** 00928 00929 ***************************************************************/ 00930 00931 FileProxy proxy = new FileProxy (base); 00932 FilePath[] paths = proxy.toList (&filter); 00933 00934 // add packages only if there's something in them 00935 if (paths.length) 00936 deps.pkgs ~= base; 00937 00938 foreach (FilePath x; paths) 00939 { 00940 // combine base path with listed file 00941 FilePath spliced = new FilePath (x.splice (base)); 00942 00943 // recurse if this is a directory ... 00944 proxy = new FileProxy (spliced); 00945 if (proxy.isDirectory) 00946 scanFiles (deps, spliced); 00947 else 00948 deps.mods ~= proxy; 00949 } 00950 } 00951 00952 00953 /*********************************************************************** 00954 00955 ***********************************************************************/ 00956 00957 Dependencies deps; 00958 scanFiles (deps, new FilePath (r"\dmd\src\mango")); 00959 00960 Stdout.put ("-----------------").cr(); 00961 foreach (FileProxy mod; deps.mods) 00962 Stdout.put (mod.getPath()).cr(); 00963 00964 Stdout.put ("-----------------").cr(); 00965 foreach (FilePath pkg; deps.pkgs) 00966 Stdout.put (pkg).cr(); 00967 } 00968 00969 00970 /******************************************************************************* 00971 00972 Open an internet connection, and copy home page to console (via 00973 Chris Miller's socket.d). We could use a line-by-line approach in 00974 the same manner as above since both Files & Sockets are conduits. 00975 All conduits are interchangable with others. 00976 00977 *******************************************************************************/ 00978 00979 static void testSocket() 00980 { 00981 // create a socket and connect it to Walter's site 00982 SocketConduit sc = new SocketConduit(); 00983 sc.connect (new InternetAddress("www.digitalmars.com", 80)); 00984 00985 // construct a writer and bind it to the socket 00986 IWriter write = new DisplayWriter (sc); 00987 00988 // send HTTP request - flush the output 00989 write ("GET /d/intro.html HTTP/1.1\r\n" 00990 "Host: www.digitalmars.com\r\n\r\n") (); 00991 00992 // set read-timeout to 0.5 seconds (avoids stalling) 00993 sc.setTimeout (System.Interval.Millisec * 500); 00994 00995 // stream home-page directly to console conduit 00996 Stdout.conduit.copy (sc); 00997 } 00998 00999 01000 /******************************************************************************* 01001 01002 Use a ColumnWriter to write formatted data onto the console. Note 01003 that we map the ColumnWriter directly into the Stdout buffer. 01004 01005 *******************************************************************************/ 01006 01007 static void testColumn() 01008 { 01009 static int[] columns = [0, 4, 14, 24]; 01010 01011 // map a ColumnWriter directly onto Stdout 01012 ColumnWriter cw = new ColumnWriter (Stdout.getBuffer(), new ColumnList(columns)); 01013 01014 cw (1) (20.34) ("test") ("next") (CR) (); 01015 } 01016 01017 /******************************************************************************* 01018 01019 Get a line of input from the console, and extract an integer. Input 01020 from the console always waits until CR is pressed (at the OS level). 01021 01022 *******************************************************************************/ 01023 01024 static void testStdin() 01025 { 01026 int x; 01027 01028 // display a prompt - flush the output, since there is no 'newline' 01029 Stdout ("Enter a number: ") (); 01030 01031 // wait for <cr>, then convert input to integer. 01032 Stdin (x); 01033 } 01034 01035 01036 version (Ares) {} 01037 else 01038 { 01039 import std.regexp; 01040 01041 /******************************************************************************* 01042 01043 Use RegExp to scan words via a buffer. 01044 01045 *******************************************************************************/ 01046 01047 static void wordRegex (IBuffer buffer) 01048 { 01049 // create a new regex tokenizer for words 01050 RegexTokenizer rt = new RegexTokenizer (new RegExp(r"\w+", null)); 01051 01052 // create a token to hold tokenized output, and bind it to the buffer 01053 CompositeToken word = new CompositeToken (rt, buffer); 01054 01055 // read buffer a word at a time. Method next() returns false when no 01056 // more tokens are found 01057 while (word.next) 01058 Stdout (word) (CR); 01059 } 01060 01061 01062 01063 /******************************************************************************* 01064 01065 Use RegExp to scan file content via a buffer. Buffered scanning 01066 avoids loading the entire file into memory at one time. 01067 01068 *******************************************************************************/ 01069 01070 static void testFileRegex() 01071 { 01072 // open a file for reading 01073 FileConduit fc = new FileConduit ("test.txt"); 01074 01075 // extract words from file 01076 wordRegex (fc.createBuffer); 01077 } 01078 01079 01080 /******************************************************************************* 01081 01082 open an internet connection and scan home-page for words. 01083 01084 *******************************************************************************/ 01085 01086 static void testSocketRegex() 01087 { 01088 // create a socket and connect it to Walter's site 01089 SocketConduit sc = new SocketConduit(); 01090 sc.connect (new InternetAddress("www.digitalmars.com", 80)); 01091 01092 // construct a writer and bind it to the socket 01093 IWriter write = new DisplayWriter (sc); 01094 01095 // write HTTP request, and flush output socket 01096 write ("GET /d/intro.html HTTP/1.1\r\n" 01097 "Host: www.digitalmars.com\r\n\r\n") (); 01098 01099 // set read-timeout to 0.5 seconds (avoids stalling) 01100 sc.setTimeout (System.Interval.Millisec * 500); 01101 01102 // scan words out of home page 01103 wordRegex (sc.createBuffer); 01104 } 01105 01106 01107 /******************************************************************************* 01108 01109 Read lines from a file, and scan each line for words. This shows 01110 how to map the content of one buffer into another without copying 01111 any data. Unlikely to be a common activity. 01112 01113 *******************************************************************************/ 01114 01115 static void testLineRegex() 01116 { 01117 // open a file for reading 01118 FileConduit fc = new FileConduit ("test.txt"); 01119 01120 // create a token for lines, and map it onto the file buffer. 01121 CompositeToken line = new CompositeToken (Tokenizers.line, fc); 01122 01123 // create a seperate buffer for scanning within each line. We will 01124 // set the content for this buffer as we read each line. Note that 01125 // if we used the file buffer directly, then we'd continue reading 01126 // words right past the end of the line. This is because the file 01127 // buffer would just reload itself instead of halting at the line 01128 // termimator. 01129 Buffer rescan = new Buffer; 01130 01131 // scan all lines in the file, including the final one 01132 while (line.get) 01133 { 01134 // map our rescan buffer onto the line content 01135 rescan.setValidContent (line.toString); 01136 01137 // scan just this line for words 01138 wordRegex (rescan); 01139 } 01140 01141 } 01142 } 01143 01144 /******************************************************************************* 01145 01146 Display the size of a file 01147 01148 *******************************************************************************/ 01149 01150 static void testFileSize() 01151 { 01152 FileProxy fp = new FileProxy ("test.txt"); 01153 01154 Stdout (fp.getPath) 01155 (" is ") 01156 (fp.getSize) 01157 (" bytes long") 01158 (CR); 01159 } 01160 01161 01162 /******************************************************************************* 01163 01164 list a set of files 01165 01166 *******************************************************************************/ 01167 01168 static void testFileList() 01169 { 01170 FileProxy proxy = new FileProxy (r"."); 01171 01172 foreach (FilePath path; proxy.toList()) 01173 Stdout.put(path).cr(); 01174 } 01175 01176 /******************************************************************************* 01177 01178 list a set of files 01179 01180 *******************************************************************************/ 01181 01182 static void testFilePath() 01183 { 01184 FilePath path = new FilePath (r"c:\1\2\3\4\abc.foo.bar"); 01185 01186 Stdout << path << CR; 01187 01188 Uri uri = path.toUri(); 01189 Stdout << uri.getScheme() << CR 01190 << uri.getHost() << CR 01191 << uri.getPath() << CR 01192 << uri.getPort() << CR 01193 << uri << CR; 01194 01195 uri = new Uri (uri.toString()); 01196 Stdout << uri.getScheme() << CR 01197 << uri.getHost() << CR 01198 << uri.getPath() << CR 01199 << uri.getPort() << CR 01200 << uri << CR; 01201 01202 path = new FilePath (uri); 01203 01204 Stdout << path << CR; 01205 } 01206 01207 01208 /******************************************************************************* 01209 01210 Construct a memory-mapped buffer upon a 200MB file. Note that we 01211 should close both the conduit and buffer when finished. 01212 01213 Note also that Win32 takes a while to close the initial file if 01214 it has just been created or resized. Subsequently opening the 01215 file as ReadWriteExising performs admirably. I imagine it's to 01216 do with spooling a gazillion dirty pages to the drive? 01217 01218 *******************************************************************************/ 01219 /+ 01220 version (MappedFile) 01221 { 01222 void testMappedFile() 01223 { 01224 FileConduit conduit = new FileConduit ("test.bin", FileStyle.ReadWriteCreate); 01225 conduit.seek (200_000_000); 01226 conduit.truncate (); 01227 01228 MappedFile buffer = new MappedFile (conduit); 01229 buffer.setPosition (100_000_000); 01230 buffer.append ("test"); 01231 buffer.close (); 01232 01233 conduit.close (); 01234 } 01235 } 01236 +/ 01237 01238 /******************************************************************************* 01239 01240 Use Composite IO to read and write a data-set. See CompositeReader 01241 and CompositeWriter for more on this. 01242 01243 *******************************************************************************/ 01244 01245 static void testCompositeIO() 01246 { 01247 // define a serializable class (via interfaces) 01248 class Wumpus : IReadable, IWritable 01249 { 01250 private int x = 11, 01251 y = 112, 01252 z = 1024; 01253 01254 void write (IWriter output) 01255 { 01256 output (x) (y) (z); 01257 } 01258 01259 void read (IReader input) 01260 { 01261 input (x) (y) (z); 01262 } 01263 01264 } 01265 01266 // construct a Wumpus 01267 Wumpus wumpus = new Wumpus; 01268 01269 // open a file for IO 01270 FileConduit fc = new FileConduit ("random.bin", FileStyle.ReadWriteCreate); 01271 01272 // construct composite reader & writer upon the file, with binary IO 01273 IWriter write = new Writer (fc); 01274 IReader read = new Reader (fc); 01275 01276 // write the Wumpus (and flush it) 01277 write (wumpus) (); 01278 01279 // rewind to file start 01280 fc.seek (0); 01281 01282 // read Wumpus back again 01283 read (wumpus); 01284 01285 fc.close(); 01286 } 01287 01288 01289 01290 /******************************************************************************* 01291 01292 One can perform direct IO on a conduit, simply by mapping a Buffer 01293 onto a local array. No additional buffering takes place but readers, 01294 writers, and tokenizers can't tell the difference: they may all be 01295 used without issue. 01296 01297 This example uses the same direct-buffer for both reading & writing. 01298 However, seperate buffers may be used as appropriate. 01299 01300 *******************************************************************************/ 01301 01302 static void testDirectIO() 01303 { 01304 // open a file for IO 01305 auto FileConduit fc = new FileConduit ("random.bin", FileStyle.ReadWriteCreate); 01306 01307 // direct IO area (on the stack) 01308 ubyte[1024] content; 01309 01310 // map a buffer onto local content. State all of it is valid content. 01311 // There are other IBuffer methods, such as setValidContent(), which 01312 // stipulate how much data is really in the buffer. 01313 IBuffer direct = new Buffer(content, content.length); 01314 01315 // map our buffer onto the file 01316 direct.setConduit(fc); 01317 01318 // mess with the content[] ... 01319 // ... 01320 // ... 01321 // ... 01322 01323 // write directly from the local buffer (might use fc.flush() instead) 01324 fc.write (direct); 01325 01326 // rewind to file start 01327 fc.seek (0); 01328 01329 // make space for reading 01330 direct.clear(); 01331 01332 // read it all back in again 01333 int count = fc.read (direct); 01334 delete fc; 01335 01336 } 01337 01338 01339 /******************************************************************************* 01340 01341 *******************************************************************************/ 01342 01343 static void testUri() 01344 { 01345 MutableUri uri; 01346 01347 uri = new MutableUri ("ftp1://Me:My@a:21"); 01348 Stdout << uri << CR; 01349 01350 uri.parse ("http://a:8080/b/c/d;p?q=bar of soap#fragmented"); 01351 Stdout << uri << CR; 01352 01353 Stdin.wait(); 01354 01355 for (int i=10_000_000; i > 0; --i) 01356 uri.parse ("http://a:8080/b/c/d;p?q=bar of soap#fragmented"); 01357 } 01358 01359 01360 /****************************************************************************** 01361 ************************ SocketServer testing ********************************* 01362 *******************************************************************************/ 01363 01364 01365 01366 /******************************************************************************* 01367 01368 Test the http server by sending it a few thousand requests. Note 01369 that we don't use a reader or a writer here, though we could just 01370 as easily have done so. 01371 01372 Also note that (Gentoo) linux has a hard time scavenging sockets 01373 fast enough to complete more than around 6000 iterations. Without 01374 the appropriate guru incantations to make ulimit work as desired, 01375 we just limit the iterations to a more agreeable level. Testing 01376 under Win32 seems to be fine at the 100,000 iteration mark. 01377 01378 *******************************************************************************/ 01379 01380 void testClient () 01381 { 01382 Buffer buf = new Buffer(1024); 01383 InternetAddress addr = new InternetAddress("localhost", 80); 01384 01385 for (int i=10000; --i >= 0;) 01386 { 01387 // connect to the server 01388 SocketConduit socket = new SocketConduit (); 01389 socket.connect (addr); 01390 01391 // reset buffer for another go around 01392 buf.clear (); 01393 01394 // would need this if we were using Reader/Writer IO 01395 // buf.setConduit(socket); 01396 01397 // send a request. This will be serviced by our IProvider 01398 buf.append ("GET / HTTP/1.1\n\n"); 01399 socket.write (buf); 01400 01401 // wait for something to be returned (you can set a timeout) 01402 socket.read (buf); 01403 01404 // dump response to the console 01405 //Stdout.conduit.write (buf); 01406 01407 // when we close this socket, recycle it immediately! 01408 //socket.setLingerPeriod (0); 01409 01410 // attempt a graceful shutdown 01411 //socket.shutdown (); 01412 01413 // close and destroy socket (the latter will do both) 01414 socket.close (); 01415 delete socket; 01416 } 01417 } 01418 01419 01420 /******************************************************************************* 01421 01422 Create an http server with the given IProvider 01423 01424 *******************************************************************************/ 01425 01426 void testServer (IProvider provider) 01427 { 01428 // bind to port 80 on a local address 01429 InternetAddress addr = new InternetAddress (80); 01430 01431 // create a (1 thread) server using the IProvider to service requests 01432 HttpServer server = new HttpServer (provider, addr, 1); 01433 01434 // start listening for requests (but this thread does not listen) 01435 server.start (); 01436 01437 // pause for some console input 01438 Stdout.put("hit return to start the client test ...").flush(); 01439 Stdin.wait (); 01440 01441 // send a few thousand requests 01442 long time = System.getMillisecs; 01443 testClient (); 01444 Stdout.put (System.getMillisecs - time).cr(); 01445 } 01446 01447 01448 /******************************************************************************* 01449 01450 Declare a class for handling http requests. This one just simply 01451 returns a status page 01452 01453 *******************************************************************************/ 01454 01455 void testHttpServer () 01456 { 01457 class Provider : HttpProvider 01458 { 01459 void service (HttpRequest request, HttpResponse response) 01460 { 01461 response.sendError (HttpResponses.OK); 01462 } 01463 } 01464 01465 // create a new http-provider, and attach it to a server 01466 testServer (new Provider()); 01467 } 01468 01469 01470 /******************************************************************************* 01471 01472 Test the servlet wrapper. Point your Browser at http://127.0.0.1 01473 and optionally add a path, query params, etc ... 01474 01475 *******************************************************************************/ 01476 01477 void testServletEngine () 01478 { 01479 /*********************************************************************** 01480 01481 Return a file. Deliberately supports GET requests only. 01482 01483 ***********************************************************************/ 01484 01485 class FileServlet : MethodServlet 01486 { 01487 void doGet (IServletRequest request, IServletResponse response) 01488 { 01489 response.copyFile (request.getContext(), request.getPathInfo()); 01490 } 01491 } 01492 01493 01494 /*********************************************************************** 01495 01496 A whole bunch of diagnostic stuff, plus cookie return and 01497 rudimentary form processing. 01498 01499 ***********************************************************************/ 01500 01501 class MyServlet : Servlet 01502 { 01503 void service (IServletRequest request, IServletResponse response) 01504 { 01505 Uri uri = request.getUri(); 01506 01507 // log everything to the console 01508 Stdout ("------------------------") 01509 (CR) 01510 ("Uri: ") 01511 (uri) 01512 () 01513 ("------------------------") 01514 (CR) 01515 ("Headers:") 01516 (CR) 01517 (request.getHeaders) 01518 ("------------------------") 01519 (CR) 01520 ("Cookies:") 01521 (CR) 01522 (request.getCookies) 01523 ("------------------------") 01524 (CR) 01525 ("Parameters:") 01526 (CR) 01527 (request.getParameters) 01528 ("------------------------") 01529 (CR); 01530 01531 // display the Servlet environment 01532 Stdout ("encoding: ") 01533 (request.getCharacterEncoding) 01534 (CR) 01535 ("content length: ") (request.getContentLength) 01536 (CR) 01537 ("content type: ") (request.getContentType) 01538 (CR) 01539 ("protocol: ") (request.getProtocol) 01540 (CR) 01541 ("scheme: ") (uri.getScheme) 01542 (CR) 01543 ("method: ") (request.getMethod) 01544 (CR) 01545 ("host name: ") (request.getServerName) 01546 (CR) 01547 ("host port: ") (request.getServerPort) 01548 (CR) 01549 //.put("remote address: ").put(request.getRemoteAddress()).cr() 01550 //.put("remote host: ").put(request.getRemoteHost()).cr() 01551 ("path info: ") (request.getPathInfo) 01552 (CR) 01553 ("query: ") (uri.getQuery()) 01554 (CR) 01555 ("path: ") (uri.getPath()) 01556 (CR) 01557 ("context path: ") (request.getContextPath) 01558 (CR) 01559 (CR) 01560 (CR); 01561 01562 int i = request.getContentLength(); 01563 01564 if (i > 0) 01565 { 01566 byte[] content = new byte[i]; 01567 01568 request.getReader.getPostData (content); 01569 Stdout.print ("Content:\n>>%s<<\n\n\n", content); 01570 } 01571 01572 // send a cookie to the user-agent ... 01573 response.getCookies().add (new Cookie ("fu", "'bar of soap'")); 01574 01575 // send a form to the user-agent ... 01576 IWriter write = response.getWriter(); 01577 write ("<HTML><HEAD><TITLE>Form</TITLE></HEAD>") 01578 ("<BODY><FORM method=POST action=\"/context/test\">") 01579 ("Enter a POST parameter: ") 01580 ("<INPUT type=text name=\"name\"><P>") 01581 ("<INPUT type=hidden name=\"hidden\" value=\"test\"><P>") 01582 ("<INPUT type=submit>") 01583 ("<?FORM></BODY></HTML>") 01584 (CR); 01585 01586 } 01587 } 01588 01589 01590 // construct a servlet-provider 01591 ServletProvider sp = new ServletProvider(); 01592 01593 // map all html requests to our file servlet 01594 IRegisteredServlet files = sp.addServlet (new FileServlet(), "files"); 01595 sp.addMapping ("*.html", files); 01596 sp.addMapping ("*.htm", files); 01597 01598 // map all other request to our test servlet 01599 IRegisteredServlet test = sp.addServlet (new MyServlet(), "test"); 01600 sp.addMapping ("/", test); 01601 01602 // fire up a server 01603 testServer (sp); 01604 } 01605 01606 01607 /******************************************************************************* 01608 01609 Shows a variety of ways in which to access data returned from 01610 a client-side socket connection. 01611 01612 *******************************************************************************/ 01613 01614 void testHttpClient () 01615 { 01616 /*********************************************************************** 01617 01618 Bulk copy from input to Stdout 01619 01620 ***********************************************************************/ 01621 01622 void readBulk (IConduit conduit) 01623 { 01624 // stream directly to console 01625 Stdout.conduit.copy (conduit); 01626 } 01627 01628 /*********************************************************************** 01629 01630 Unwound version of the above, where we explicitly move 01631 data between endpoints using a buffer 01632 01633 ***********************************************************************/ 01634 01635 void readBulkExplicit (IConduit conduit) 01636 { 01637 // create a buffer for transferring content 01638 IBuffer buffer = conduit.createBuffer (); 01639 01640 // stream the data from file to stdout. This is probably as fast as 01641 // one can practically make operations of this type. 01642 while (conduit.read (buffer) != conduit.Eof) 01643 Stdout.conduit.write (buffer); 01644 01645 // ensure the writer actually wrote everything 01646 buffer.flush (); 01647 } 01648 01649 /*********************************************************************** 01650 01651 Read input a line at a time from the input. You can access 01652 the line content via method Token.toString() 01653 01654 ***********************************************************************/ 01655 01656 void readLines (IConduit conduit) 01657 { 01658 // create a Token and bind it to both the conduit and a line-tokenizer 01659 CompositeToken line = new CompositeToken (Tokenizers.line, conduit); 01660 01661 // read data a line at a time. Method next() returns false when no more 01662 // delimiters are found. Note there may be an unterminated line at eof 01663 while (line.get) 01664 Stdout (line) (CR); 01665 } 01666 01667 /*********************************************************************** 01668 01669 Read input a char at a time. This will read in big chunks 01670 of data from the input, but spit them out one character at 01671 a time. While this is a lot faster then reading one char 01672 at a time from the OS (the typical approach), this style 01673 of reading is not recommended. Instead, try the 'chunked' 01674 approach (below). 01675 01676 ***********************************************************************/ 01677 01678 void readChars (IConduit conduit) 01679 { 01680 // create a reader on the conduit 01681 Reader reader = new Reader (conduit); 01682 01683 // read a single character at a time, until we run out of them. 01684 // An exception will eventually be thrown because we're using 01685 // the 'formatted' data approach 01686 try { 01687 while (true) 01688 { 01689 char c; 01690 reader (c); 01691 Stdout (c); 01692 } 01693 } catch (IOException x){} 01694 } 01695 01696 /*********************************************************************** 01697 01698 Read big chunks of data, and process them as such. Each read 01699 operation will eat as much as there is from the input, up to 01700 the size limit of the buffer. 01701 01702 ***********************************************************************/ 01703 01704 void readChunks (IConduit conduit) 01705 { 01706 IBuffer buffer = new Buffer(1024); 01707 01708 while (conduit.read (buffer) != conduit.Eof) 01709 { 01710 Stdout (buffer.toString); 01711 buffer.clear (); 01712 } 01713 } 01714 01715 /*********************************************************************** 01716 01717 unwound version of the above, where we setup buffer space 01718 on the stack (instead of the heap). We need to explicitly 01719 ask the buffer how much data is actually available. One 01720 could use the return value from read() as the number of 01721 bytes available instead (in this particular case), or 01722 use buffer.toString() as in the above case 01723 01724 ***********************************************************************/ 01725 01726 void readChunksExplicit (IConduit conduit) 01727 { 01728 char[1024] content; 01729 01730 IBuffer buffer = new Buffer (content); 01731 01732 while (conduit.read (buffer) != conduit.Eof) 01733 { 01734 Stdout (content[0..buffer.readable()]); 01735 buffer.clear (); 01736 } 01737 } 01738 01739 01740 /*********************************************************************** 01741 01742 Open a web-site connection, and process the returned page 01743 01744 ***********************************************************************/ 01745 01746 // create a socket and connect it to Walter's site 01747 SocketConduit sc = new SocketConduit(); 01748 sc.connect (new InternetAddress("www.digitalmars.com", 80)); 01749 01750 // construct a writer and bind it to the socket 01751 IWriter w = new FlushWriter (sc); 01752 01753 // send HTTP request 01754 w.put ("GET /d/intro.html HTTP/1.1") 01755 .cr () 01756 .put ("Host: www.digitalmars.com") 01757 .cr () 01758 .cr (); 01759 01760 // set read-timeout to 1 second (avoids stalling for ever!) 01761 sc.setTimeout (System.Interval.Second); 01762 01763 //readBulk (sc); 01764 //readBulkExplicit(sc); 01765 //readLines(sc); 01766 //readChars(sc); 01767 //readChunks(sc); 01768 readChunksExplicit(sc); 01769 01770 // flush output 01771 Stdout (); 01772 } 01773 01774 01775 /******************************************************************************* 01776 01777 Extract client-side headers from an HTTP reply 01778 01779 *******************************************************************************/ 01780 01781 void testHttpClient2 () 01782 { 01783 // create a socket and connect it to Walter's site 01784 SocketConduit sc = new SocketConduit; 01785 sc.connect (new InternetAddress("www.digitalmars.com", 80)); 01786 01787 // construct a writer and bind it to the socket 01788 IWriter w = new FlushWriter (sc); 01789 01790 // send HTTP request 01791 w.put ("GET /d/intro.html HTTP/1.1") 01792 .cr () 01793 .put ("Host: www.digitalmars.com") 01794 .cr () 01795 .cr (); 01796 01797 // set read-timeout to 1 second (avoids stalling for ever!) 01798 sc.setTimeout (System.Interval.Second); 01799 01800 // create an input buffer 01801 IBuffer buffer = sc.createBuffer; 01802 01803 // extract all headers 01804 HttpHeaders headers = new HttpHeaders; 01805 headers.parse (buffer); 01806 01807 // display parsed headers -- these should match HttpHeader.HttpHeaders 01808 foreach (HeaderElement header; headers) 01809 Stdout.put (header.name.value) 01810 .put (header.value) 01811 .cr (); 01812 01813 // display remaining content 01814 while (sc.read (buffer) != sc.Eof) 01815 { 01816 Stdout (buffer.toString); 01817 buffer.clear (); 01818 } 01819 Stdout (); 01820 } 01821 01822 /******************************************************************************* 01823 01824 Poke an HTTP server, using HttpClient. 01825 01826 *******************************************************************************/ 01827 01828 void testHttpClient3() 01829 { 01830 // create client for a GET request 01831 auto HttpClient client = new HttpClient (HttpClient.Get, "http://www.digitalmars.com/d/intro.html"); 01832 01833 // setup a Host header 01834 client.getRequestHeaders.add (HttpHeader.Host, client.getUri.getHost); 01835 01836 // make request 01837 IBuffer b = client.open (); 01838 01839 // check return status for validity 01840 if (client.isResponseOK) 01841 { 01842 // extract content length (be aware of -1 return, for no header) 01843 int length = client.getResponseHeaders.getInt (HttpHeader.ContentLength); 01844 if (length < 0) 01845 length = int.max; 01846 01847 // display all returned headers 01848 Stdout.put (client.getResponseHeaders); 01849 01850 // display remaining content 01851 client.read (delegate (char[] c){Stdout.put(c);}, length); 01852 Stdout (); 01853 } 01854 else 01855 Stderr.put (client.getResponse); 01856 } 01857 01858 01859 01860 01861 /****************************************************************************** 01862 **************************** Cache testing ************************************ 01863 *******************************************************************************/ 01864 01865 01866 01867 /******************************************************************************* 01868 01869 01870 *******************************************************************************/ 01871 01872 void testPlainCache() 01873 { 01874 PlainCache cache = new PlainCache (2); 01875 01876 cache.put ("a", new Payload); 01877 cache.put ("b", new Payload); 01878 cache.put ("c", new Payload); 01879 cache.put ("c", new Payload); 01880 01881 cache.extract ("b"); 01882 assert (cache.get("a")); 01883 assert (cache.get("c")); 01884 assert (cache.get("b") is null); 01885 } 01886 01887 /******************************************************************************* 01888 01889 QueuedCache maintains a linked list of items, in addition to a 01890 hashmap. Any reference to an item places it at the list head, 01891 resulting in the LRU items always being left at the tail. When 01892 the list becomes full, tail items are dropped and their places 01893 reused. 01894 01895 This is great for keeping commonly accessed items around, while 01896 limiting the amount of memory used. 01897 01898 Typically, the queue size would be set in the hundreds (perhaps 01899 thousands) but we just use 2 for testing purposes. 01900 01901 *******************************************************************************/ 01902 01903 void testQueuedCache() 01904 { 01905 QueuedCache cache = new QueuedCache (2); 01906 01907 cache.put ("a", new Payload); 01908 cache.put ("b", new Payload); 01909 cache.put ("c", new Payload); 01910 cache.put ("c", new Payload); 01911 01912 assert (cache.get("a") is null); 01913 assert (cache.get("c")); 01914 } 01915 01916 /******************************************************************************* 01917 01918 Stuff some data into a FileBucket, and pull it out again. 01919 01920 *******************************************************************************/ 01921 01922 void testFileBucket() 01923 { 01924 char[] text = "this is a test"; 01925 01926 FileBucket bucket = new FileBucket (new FilePath ("bucket.bin"), FileBucket.HalfK, 0); 01927 01928 // insert some data, and retrieve it again 01929 bucket.put ("a", text); 01930 char[] b = cast(char[]) bucket.get ("a"); 01931 01932 assert (b == text); 01933 bucket.close(); 01934 } 01935 01936 01937 /******************************************************************************* 01938 01939 Use a combination of QueuedCache and FileBucket to spill LRU 01940 cache entries onto the hard-drive, and then recover them intact. 01941 01942 This demonstrates what one can do with the IPickle notion. 01943 01944 *******************************************************************************/ 01945 01946 void testVirtualCache() 01947 { 01948 FileBucket bucket = new FileBucket (new FilePath ("bucket.bin"), FileBucket.HalfK); 01949 VirtualCache cache = new VirtualCache (bucket, 2); 01950 PickleRegistry.enroll (new Payload); 01951 01952 cache.put ("a", new Payload); 01953 cache.put ("b", new Payload); 01954 cache.put ("c", new Payload); 01955 01956 assert (cache.get("a")); 01957 assert (cache.get("c")); 01958 assert (cache.get("b")); 01959 bucket.close(); 01960 } 01961 01962 /******************************************************************************* 01963 01964 01965 *******************************************************************************/ 01966 01967 void testProtocol() 01968 { 01969 class Protocol : Payload 01970 { 01971 char[] x; 01972 int y = 10; 01973 bool z = true; 01974 01975 this () 01976 { 01977 x = "fred"; 01978 } 01979 01980 static this() 01981 { 01982 PickleRegistry.enroll(new Protocol); 01983 } 01984 01985 void write (IWriter w) 01986 { 01987 super.write (w); 01988 w.put (x) 01989 .put (y) 01990 .put (z); 01991 } 01992 01993 void read (IReader r) 01994 { 01995 super.read (r); 01996 r.get (x) 01997 .get (y) 01998 .get (z); 01999 02000 assert (x == "fred"); 02001 assert (y == 10); 02002 assert (z == true); 02003 } 02004 02005 Payload create () 02006 { 02007 return new Protocol; 02008 } 02009 02010 char[] getGuid () 02011 { 02012 return this.classinfo.name; 02013 } 02014 } 02015 02016 Protocol p = new Protocol; 02017 02018 Buffer b = new Buffer (1024); 02019 ProtocolWriter w = new ProtocolWriter (b); 02020 ProtocolReader r = new ProtocolReader (b); 02021 02022 w.put (w.Command.Exception, "mychannel", p); 02023 02024 ubyte cmd; 02025 char[] channel, 02026 element; 02027 02028 p = cast(Protocol) r.getPayload (channel, element, cmd); 02029 } 02030 02031 02032 /******************************************************************************* 02033 02034 02035 *******************************************************************************/ 02036 02037 version (Isolated){} 02038 else 02039 { 02040 void testRollingFileLog() 02041 { 02042 Logger l = Logger.getLogger ("test"); 02043 l.addAppender (new RollingFileAppender (new FilePath (r"e:\test.log"), 3, 1024, new DateLayout)); 02044 02045 for (int i=100; --i;) 02046 l.error ("weqwer er wer werqwer wer wer wer wr wqrwe qrw rwe rwqerw"); 02047 } 02048 } 02049 02050 02051 02052 /****************************************************************************** 02053 **************************** Cluster testing ********************************** 02054 *******************************************************************************/ 02055 02056 02057 02058 /******************************************************************************* 02059 02060 Join a socket to a multicast group, and send the group a packet. 02061 02062 *******************************************************************************/ 02063 02064 void testMulticast() 02065 { 02066 class MyListener : SocketListener 02067 { 02068 this (ISocketReader reader, IBuffer buffer) 02069 { 02070 super (reader, buffer); 02071 } 02072 02073 void notify (IBuffer buffer) 02074 { 02075 Stdout.print ("listener received %d bytes\n", buffer.readable()); 02076 } 02077 02078 void exception (char[] msg) 02079 { 02080 Stdout.print ("listener error: %s\n", msg); 02081 } 02082 } 02083 02084 //auto MulticastSocket ms = new MulticastSocket (); 02085 MulticastSocket ms = new MulticastSocket (); 02086 InternetAddress ia = new InternetAddress ("226.1.1.1", 4444); 02087 02088 ms.join (ia); 02089 MyListener s = new MyListener (ms, new Buffer (2000)); 02090 s.start (); 02091 02092 Stdin.wait (); 02093 //s.pause (); 02094 //s.resume (); 02095 02096 byte[1000] xx; 02097 Buffer b = new Buffer (xx, xx.length); 02098 02099 ms.write (b, ia); 02100 Stdin.wait (); 02101 //s.cancel (); 02102 } 02103 02104 /******************************************************************************* 02105 02106 *******************************************************************************/ 02107 02108 void testClusterCache() 02109 { 02110 //ClusterServer cs = new ClusterServer (new InternetAddress(4567), 1); 02111 //cs.start (); 02112 02113 //auto FileConduit config = new FileConduit ("cluster.properties"); 02114 //Cluster cluster = new Cluster (logger, config); 02115 Cluster cluster = new Cluster (logger, 4567); 02116 02117 //NetworkCache cc = new NetworkCombo (cluster, "myChannel", new PlainCache); 02118 NetworkCache cc = new NetworkCache (cluster, "myChannel"); 02119 02120 InvalidatorPayload p = new InvalidatorPayload; 02121 02122 cc.put ("key", p); 02123 // cc.invalidate ("key"); 02124 for (int i=100_000; i; --i) 02125 { 02126 // p.setText ("fubar"); 02127 // cc.put ("key", p); 02128 // cc.invalidate ("key"); 02129 IPayload p = cc.get ("key"); 02130 // if ((i & 0x3f) == 0) 02131 // System.sleep (System.Interval.Second); 02132 /* 02133 p = cast(InvalidatorPayload) cc.get ("key"); 02134 assert (p); 02135 assert (p.getText == "fubar"); 02136 02137 cc.invalidate ("key"); 02138 p = cast(InvalidatorPayload) cc.get ("key"); 02139 */ 02140 } 02141 //assert (p is null); 02142 02143 // cc.invalidate ("key"); 02144 02145 //Stdin.wait (); 02146 } 02147 02148 02149 /******************************************************************************* 02150 02151 *******************************************************************************/ 02152 02153 void testClusterQueue() 02154 { 02155 class Listen : IEventListener 02156 { 02157 void notify (IEvent event, IPayload payload) 02158 { 02159 Stdout.print ("recieved queue entry from channel '%s'\n", event.getChannel.getName); 02160 } 02161 } 02162 02163 //ClusterServer cs = new ClusterServer (new InternetAddress(4567), 1); 02164 //cs.start (); 02165 02166 Cluster cluster = new Cluster (logger, 4567); 02167 NetworkQueue queue = new NetworkQueue (cluster, "queue.channel"); 02168 02169 queue.createConsumer (new Listen); 02170 queue.put (new InvalidatorPayload); 02171 queue.put (new InvalidatorPayload); 02172 02173 Stdin.wait (); 02174 } 02175 02176 02177 /******************************************************************************* 02178 02179 *******************************************************************************/ 02180 02181 void testInvalidatee() 02182 { 02183 ICluster c = new Cluster (logger); 02184 02185 CacheInvalidatee dst = new CacheInvalidatee (c, "abc", new PlainCache); 02186 CacheInvalidator src = new CacheInvalidator (c, "abc"); 02187 02188 src.invalidate ("key1"); 02189 02190 Stdin.wait (); 02191 } 02192 02193 02194 /******************************************************************************* 02195 02196 02197 *******************************************************************************/ 02198 02199 void testClusterServer() 02200 { 02201 ClusterServer cs = new ClusterServer (new InternetAddress(81), 1); 02202 SocketConduit sc = new SocketConduit (); 02203 cs.start(); 02204 02205 sc.connect (new InternetAddress ("127.0.0.1", 81)); 02206 Stdin.wait (); 02207 } 02208 02209 02210 /******************************************************************************* 02211 02212 02213 *******************************************************************************/ 02214 02215 02216 void testClusterMessage() 02217 { 02218 class MessageListener : IEventListener 02219 { 02220 void notify (IEvent event, IPayload payload) 02221 { 02222 IMessage message = cast(IMessage) payload; 02223 02224 Stdout.print ("Replying to message\n"); 02225 event.reply (message.getReply, new InvalidatorPayload); 02226 } 02227 } 02228 02229 class ReplyListener : IEventListener 02230 { 02231 void notify (IEvent event, IPayload payload) 02232 { 02233 Stdout.print ("Received reply\n"); 02234 } 02235 } 02236 02237 //ClusterServer cs = new ClusterServer (new InternetAddress(4567), 1); 02238 //cs.start (); 02239 02240 // open the cluster 02241 Cluster cluster = new Cluster (logger, 4567); 02242 02243 // open up a message channel 02244 NetworkMessage msg = new NetworkMessage (cluster, "message.channel", new ReplyListener); 02245 02246 // setup a listener to receive message (could do this earlier) 02247 msg.createConsumer (new MessageListener); 02248 02249 // toss a message out to the cluster 02250 msg.put (new NullMessage); 02251 02252 // wait for traffic to pass by 02253 Stdin.wait (); 02254 } 02255 02256 02257 /******************************************************************************* 02258 02259 02260 *******************************************************************************/ 02261 02262 void testCacheLoader() 02263 { 02264 class CacheLoader : ICacheLoader 02265 { 02266 bool test (IPayload p) 02267 { 02268 return false; 02269 } 02270 02271 IPayload load (char[] key, long time) 02272 { 02273 Stdout.print ("loading local cache instance\n"); 02274 return new NullMessage; 02275 } 02276 } 02277 02278 IMutableCache mc = new PlainCache; 02279 ICache c = mc.bind (new CacheLoader); 02280 02281 c.get ("abcde"); 02282 } 02283 02284 02285 /******************************************************************************* 02286 02287 02288 *******************************************************************************/ 02289 02290 void testRemoteCacheLoader() 02291 { 02292 class RemoteCacheLoader : Payload, IRemoteCacheLoader 02293 { 02294 bool test (IPayload p) 02295 { 02296 return false; 02297 } 02298 02299 IPayload load (char[] key, long time) 02300 { 02301 Stdout.print ("loading remote cache instance\n"); 02302 return new NullMessage; 02303 } 02304 02305 /********************************************************************** 02306 02307 Recover the timestamp from the provided reader 02308 02309 **********************************************************************/ 02310 02311 void read (IReader reader) 02312 { 02313 super.read (reader); 02314 } 02315 02316 /********************************************************************** 02317 02318 Emit our timestamp to the provided writer 02319 02320 **********************************************************************/ 02321 02322 void write (IWriter writer) 02323 { 02324 super.write (writer); 02325 } 02326 02327 /*********************************************************************** 02328 02329 Create a new instance of a payload, and populate it via 02330 read() using the specified reader 02331 02332 ***********************************************************************/ 02333 02334 Object create (IReader reader) 02335 { 02336 Payload r = new RemoteCacheLoader; 02337 r.read (reader); 02338 return r; 02339 } 02340 02341 /********************************************************************** 02342 02343 Return the guid for this payload. This should be unique 02344 per payload class, if said class is used in conjunction 02345 with the clustering facilities. Inspected by the Pickle 02346 utilitiy classes. 02347 02348 **********************************************************************/ 02349 02350 char[] getGuid () 02351 { 02352 return this.classinfo.name; 02353 } 02354 02355 02356 uint pause (uint wait) 02357 { 02358 return 100_000; 02359 } 02360 } 02361 02362 Cluster cluster = new Cluster (logger, 4567); 02363 NetworkCache nc = new NetworkCache (cluster, "my.channel"); 02364 IRemoteCacheLoader cl = new RemoteCacheLoader; 02365 ICache c = nc.bind (cl); 02366 02367 c.get ("abcde"); 02368 } 02369 02370 version (Isolated){} 02371 else 02372 { 02373 /******************************************************************************* 02374 02375 02376 *******************************************************************************/ 02377 02378 void testDecoder () 02379 { 02380 IWriter w = new Writer (new Buffer(100)); 02381 IReader r = new Reader (w.getBuffer()); 02382 r.setAllocator (new BufferAllocator); 02383 02384 UConverter cvt = new UConverter("utf16"); 02385 w.setEncoder (new StringEncoder16 (cvt)); 02386 r.setDecoder (new StringDecoder16 (cvt)); 02387 02388 UString ss = new UString ("hello"); 02389 02390 w (ss); 02391 r (ss); 02392 02393 Stdout.setEncoder (new StringEncoder16("utf8")); 02394 Stdout (ss) (CR); 02395 } 02396 02397 /******************************************************************************* 02398 02399 02400 *******************************************************************************/ 02401 02402 void testEncoder () 02403 { 02404 FileConduit fc = new FileConduit("foo.txt", FileStyle.ReadWriteCreate); 02405 IWriter w = new DisplayWriter(fc); 02406 w.setEncoder (new StringEncoder8 ("utf8")); 02407 w.setEncoder (new StringEncoder16 ("utf8")); 02408 w.setEncoder (new StringEncoder32 ("utf8")); 02409 w ("<?xml version='1.0'?>") ("<element") (' ') ("/>") (CR); 02410 } 02411 02412 /******************************************************************************* 02413 02414 check the Regex stuff is hooked up 02415 02416 *******************************************************************************/ 02417 02418 void testRegex () 02419 { 02420 wchar[] fields[10]; 02421 02422 Stdout.setEncoder (new StringEncoder16 ("utf8")); 02423 02424 URegex r = new URegex ("[0-9]+", URegex.Flag.CaseInsensitive); 02425 r.setText (new UString ("123abc456def789")); 02426 02427 for (int i = r.split(fields); i-- > 0;) 02428 { 02429 wchar[] x = fields[i]; 02430 Stdout.putw(x) (CR); 02431 } 02432 } 02433 02434 void testRegex1 () 02435 { 02436 Stdout.setEncoder (new StringEncoder16 ("utf8")); 02437 02438 URegex r = new URegex ("(1).*(abc).*(789)", URegex.Flag.CaseInsensitive); 02439 r.setText (new UString ("123abc456def789")); 02440 02441 if (r.next) 02442 with (r.groups()) 02443 { 02444 Stdout .putw(g0) (' ') .putw(g1) (' ') .putw(g2) (' ') .putw(g3) (CR); 02445 } 02446 } 02447 } 02448 02449 /******************************************************************************* 02450 02451 02452 *******************************************************************************/ 02453 02454 void testTextWriter () 02455 { 02456 Stdout (CR); 02457 02458 TextWriter output = new TextWriter (Stdout.getBuffer(), ", "); 02459 02460 ubyte b = 129; 02461 uint ui = uint.max; 02462 int i = -3; 02463 output (b) (ui) (i) ("hello") ("test") (CR); 02464 Stdout.println ("one two three %- 30s %010d ", "next", -10, uint.max, " foo"); 02465 Stdout.println ("%#032b '%@04x' ", 0x33, "string", '#'); 02466 Stdout.println ("%e %.3f %#X", 10.23, 10.23, 10.27); 02467 Stdout.println (Rfc1123.format (Rfc1123.utcMilli)); 02468 } 02469 02470 /******************************************************************************* 02471 02472 *******************************************************************************/ 02473 /+ 02474 extern (C) 02475 { 02476 int printf (char *format, ...) 02477 { 02478 Stderr ("invalid call to printf")(CR); 02479 return 0; 02480 } 02481 } 02482 +/ 02483 02484 /******************************************************************************* 02485 02486 02487 *******************************************************************************/ 02488 /+ 02489 02490 void testConvert () 02491 { 02492 char[200] s; 02493 char[5] g; 02494 char *zz; 02495 static uint[] ff = [1, 2, 3, 4]; 02496 char[] num = "0.12345678+1"; 02497 02498 02499 double x = Double.parse (num); 02500 double y = std.c.stdlib.strtold (num, &zz); 02501 double z = DGDouble.parse (num); 02502 02503 02504 Stdout (Double.format (s, x, 20)) (CR); 02505 Stdout (Double.format (s, y, 20)) (CR); 02506 Stdout (Double.format (s, z, 20)) (CR); 02507 Stdout.print ("%.20lf\n", x); 02508 Stdout.print ("%.20lf\n", y); 02509 Stdout.print ("%.20lf\n", z); 02510 Stdout.print ("%s\n", DGDouble.format (s, x, 4)); 02511 Stdout.print ("%s\n", DGDouble.format (s, z, 6, true, 0)); 02512 } 02513 +/ 02514 02515 /******************************************************************************* 02516 02517 02518 *******************************************************************************/ 02519 02520 int main(char[][] args) 02521 { 02522 BasicConfigurator.configure (); 02523 //PropertyConfigurator.configure ("log.properties"); 02524 logger = Logger.getLogger ("mango.unittest"); 02525 //logger.setLevel (logger.Level.Error); 02526 //logger.addAppender (new FileAppender ("log.txt", new DateLayout)); 02527 //logger.addAppender (new ConsoleAppender (new DateLayout)); 02528 //logger.addAppender (new DebugAppender (new SimpleTimerLayout)); 02529 02530 try { 02531 //testDisplay(); 02532 //testDecoder(); 02533 //testTextWriter(); 02534 //testHashMap(); 02535 //testRemoteCacheLoader(); 02536 //testCacheLoader(); 02537 //testProtocol(); 02538 //testClusterMessage(); 02539 //testRollingFileLog(); 02540 //testClusterCache(); 02541 //testClusterQueue(); 02542 //testClusterServer(); 02543 //testInvalidatee(); 02544 //testMulticast(); 02545 02546 //testAppend(); 02547 //testFile4(); 02548 //testClassSerialization(); 02549 //testFormat(); 02550 //testLayout(); 02551 //testFileSize(); 02552 //testFilePath(); 02553 //testFileList(); 02554 //testScanFiles(); 02555 //testFile1(); 02556 //testFile5(); 02557 //testToken1(); 02558 //testToken2(); 02559 //testColumn(); 02560 //testSocket(); 02561 //testStdin(); 02562 //testBuffer(); 02563 //testToken3(); 02564 //testFileRegex(); 02565 //testLineRegex(); 02566 //testSocketRegex(); 02567 //testRandomAccess(); 02568 //testCompositeIO(); 02569 //testDirectIO(); 02570 //testHttpServer(); 02571 //testServletEngine(); 02572 //testUri(); 02573 //testHttpClient(); 02574 //testHttpClient2(); 02575 //testHttpClient3(); 02576 //testQueuedCache(); 02577 //testFileBucket(); 02578 //testScanFiles(); 02579 //testVirtualCache(); 02580 //testQueuedCache(); 02581 //testPlainCache(); 02582 //testMappedFile(); 02583 //testEncoder(); 02584 //testClassIO(); 02585 //testConvert(); 02586 //testRegex(); 02587 //testRegex1(); 02588 logger.info ("Done"); 02589 } catch (Object x) 02590 { 02591 logger.fatal (x.toString); 02592 } 02593 02594 return 0; 02595 } 02596