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