[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r10687: finished documentation for impl classes, unified rest of doc (in puppetor/trunk: doc src/de/uniba/wiai/lspi/puppetor src/de/uniba/wiai/lspi/puppetor/examples src/de/uniba/wiai/lspi/puppetor/impl)



Author: kloesing
Date: 2007-06-27 18:09:47 -0400 (Wed, 27 Jun 2007)
New Revision: 10687

Modified:
   puppetor/trunk/doc/howto.aux
   puppetor/trunk/doc/howto.pdf
   puppetor/trunk/doc/howto.tex
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ClientApplication.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/DirectoryNode.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/Event.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/EventManager.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/Network.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NetworkFactory.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NetworkState.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NodeState.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ProxyNode.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/RouterNode.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ServerApplication.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/TorProcessException.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AccessingPublicWebServerOverTor.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingAndAccessingHiddenServiceOverPrivateTorNetwork.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingAndAccessingHiddenServiceOverPublicTorNetwork.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingHiddenServiceToPublicTorNetwork.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ClientApplicationImpl.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/DirectoryNodeImpl.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/EventManagerImpl.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/NetworkImpl.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ProxyNodeImpl.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/RouterNodeImpl.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ServerApplicationImpl.java
Log:
finished documentation for impl classes, unified rest of documentation, fine-tuned howto

Modified: puppetor/trunk/doc/howto.aux
===================================================================
--- puppetor/trunk/doc/howto.aux	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/doc/howto.aux	2007-06-27 22:09:47 UTC (rev 10687)
@@ -1,8 +1,9 @@
-\relax 
-\@writefile{toc}{\contentsline {section}{\numberline {1}Introduction}{1}}
-\@writefile{toc}{\contentsline {section}{\numberline {2}Installation}{2}}
-\@writefile{toc}{\contentsline {section}{\numberline {3}Example 1: Accessing public Web server over Tor}{3}}
-\@writefile{toc}{\contentsline {section}{\numberline {4}Example 2: Advertising hidden service to public Tor network}{5}}
-\@writefile{toc}{\contentsline {section}{\numberline {5}Example 3: Advertising and accessing hidden service over public Tor network}{6}}
-\@writefile{toc}{\contentsline {section}{\numberline {6}Example 4: Advertising and accessing hidden service over private Tor network}{7}}
-\@writefile{toc}{\contentsline {section}{\numberline {7}Known issues}{9}}
+\relax 
+\@writefile{toc}{\contentsline {section}{\numberline {1}Introduction}{1}}
+\@writefile{toc}{\contentsline {section}{\numberline {2}Installation}{2}}
+\@writefile{toc}{\contentsline {section}{\numberline {3}Example 1: Accessing public Web server over Tor}{3}}
+\@writefile{toc}{\contentsline {section}{\numberline {4}Example 2: Advertising hidden service to public Tor network}{5}}
+\@writefile{toc}{\contentsline {section}{\numberline {5}Example 3: Advertising and accessing hidden service over public Tor network}{6}}
+\@writefile{toc}{\contentsline {section}{\numberline {6}Example 4: Advertising and accessing hidden service over private Tor network}{8}}
+\@writefile{toc}{\contentsline {section}{\numberline {7}Architecture}{10}}
+\@writefile{toc}{\contentsline {section}{\numberline {8}Known issues}{10}}

Modified: puppetor/trunk/doc/howto.pdf
===================================================================
--- puppetor/trunk/doc/howto.pdf	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/doc/howto.pdf	2007-06-27 22:09:47 UTC (rev 10687)
@@ -1,1423 +1,1260 @@
-%PDF-1.2
-9 0 obj
-<<
-/Type/Font
-/Subtype/Type1
-/Name/F1
-/FontDescriptor 8 0 R
-/BaseFont/XEEAJR+CMR17
-/FirstChar 33
-/LastChar 196
-/Widths[249.6 458.6 772.1 458.6 772.1 719.8 249.6 354.1 354.1 458.6 719.8 249.6 301.9
-249.6 458.6 458.6 458.6 458.6 458.6 458.6 458.6 458.6 458.6 458.6 458.6 249.6 249.6
-249.6 719.8 432.5 432.5 719.8 693.3 654.3 667.6 706.6 628.2 602.1 726.3 693.3 327.6
-471.5 719.4 576 850 693.3 719.8 628.2 719.8 680.5 510.9 667.6 693.3 693.3 954.5 693.3
-693.3 563.1 249.6 458.6 249.6 458.6 249.6 249.6 458.6 510.9 406.4 510.9 406.4 275.8
-458.6 510.9 249.6 275.8 484.7 249.6 772.1 510.9 458.6 510.9 484.7 354.1 359.4 354.1
-510.9 484.7 667.6 484.7 484.7 406.4 458.6 917.2 458.6 458.6 458.6 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 576 772.1 719.8 641.1 615.3 693.3
-667.6 719.8 667.6 719.8 0 0 667.6 525.4 499.3 499.3 748.9 748.9 249.6 275.8 458.6
-458.6 458.6 458.6 458.6 693.3 406.4 458.6 667.6 719.8 458.6 837.2 941.7 719.8 249.6
-458.6]
+%PDF-1.4
+3 0 obj <<
+/Length 2577      
+/Filter /FlateDecode
 >>
+stream
+xڕ�����`��`�Oy.ljuH9e�+u^���.���e>�6���������^�UX�� ����y	��)ʁsI?9꧈Q���{YX�@J��8O�8��7��x�+�Q�>/���ٕ���q��g��C5-`U�@
+���&#����WV�"��<5�ۙ��'���Q�Z6�%&9���J*����i�K��$��-
+�����#���c-��)"B#��s���9�.ƅ_2��[��R4zs�4g���Y��'�y\mI��C\цy�+�?cށ�E�h�y�J�褅��Ӓ�(���č��bH�Yj#��3V��M�wt���}�K���B���;2Y�Q}��L'����+{����Ffev{L��(έ������l��C6 �8�rq
+J��!���Ē
+ሴ��#K`\@q��ṟ���(�:L	Ã�ѽo۵@�$	�ںU�<���ce
+}w�*���6�xUVsaEgu�8���ی<J
+�a���Cc�OD�u�D�e;`ֶ��f���9�:p7m{]�~4۸Q8q�1�B���*��#뱰��� ��V endobj
-12 0 obj
-<<
-/Type/Font
-/Subtype/Type1
-/Name/F2
-/FontDescriptor 11 0 R
-/BaseFont/NJEYML+CMR12
-/FirstChar 33
-/LastChar 196
-/Widths[272 489.6 816 489.6 816 761.6 272 380.8 380.8 489.6 761.6 272 326.4 272 489.6
-489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 489.6 272 272 272 761.6 462.4
-462.4 761.6 734 693.4 707.2 747.8 666.2 639 768.3 734 353.2 503 761.2 611.8 897.2
-734 761.6 666.2 761.6 720.6 544 707.2 734 734 1006 734 734 598.4 272 489.6 272 489.6
-272 272 489.6 544 435.2 544 435.2 299.2 489.6 544 272 299.2 516.8 272 816 544 489.6
-544 516.8 380.8 386.2 380.8 544 516.8 707.2 516.8 516.8 435.2 489.6 979.2 489.6 489.6
-489.6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 611.8 816
-761.6 679.6 652.8 734 707.2 761.6 707.2 761.6 0 0 707.2 571.2 544 544 816 816 272
-299.2 489.6 489.6 489.6 489.6 489.6 734 435.2 489.6 707.2 761.6 489.6 883.8 992.6
-761.6 272 489.6]
+2 0 obj <<
+/Type /Page
+/Contents 3 0 R
+/Resources 1 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 25 0 R
+>> endobj
+1 0 obj <<
+/Font << /F15 6 0 R /F16 9 0 R /F26 12 0 R /F8 15 0 R /F7 18 0 R /F18 21 0 R /F17 24 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+28 0 obj <<
+/Length 2399      
+/Filter /FlateDecode
 >>
+stream
+x�YI�ۺ���h���]�w�]��R�$��$d(���_����"
+L�٦�hոI����q�ʶf��(�j��R����M+[T�������-�Հ���m����0,�Ab���c��7�9��=l����3�i0���fW�Pu��Ia����9^�&���ݒI����~PQ��߰{Р�����^+b]��ffr��k�:=�`.;/Z���j���dOlY�8YzXZ�����V����(�����nq!J�����0Sy!q���7�ԝ����|�tY�]&ґ켂$i�e��{d4�؍�b'a��K��<��'�R���c�����V�~(����=.jˠ&�+2������4�`hI9<K:���������O��ea��	"aë�J�����G�j���������qN�g��`�!���w����O��q������=賊FR*��WGHj�i���J�Z�-�YK�؎=8��g�����l?bx��v9p��L�U<!�F��>r�Qe�$)p�a�1x���sM����Cc.<X>3��#޻�Bٷ�:��@��2%R8D�p���ң8c�����4J�b0�G�D9��Y����;���8�]`�,�$��	L_ϕ��7�E-��,tOUN�=Z+	�p��2P��qѭ}G`ˆN���������P$������B�7h�����#b@�:Ԟ]�i�r^R�-�`y_�P�6ReŞ�i��6a�de�p�_I�ALD�/UA<��F���gP�ѫ����&VW��E��WY�����I�ω�R"}�iٌ�o������I������՞���<sK��F1��g!���Y��(�����+.�L#�[K�5��y7�5��U�I<x�l�Q�+I�MciÕH��o�daI�V1�2y�����y���v+i��`N5�P֘�^<	���^���F?���o�ȹ鰤~-4��q�Ta���<�~F*�+�1��<��s �Q���Hᮦs�,JC���I�/��gn*�a�����hە��<N��i��A�����>�,��K4�!�\�-�u��+��J���d�OO �K�5a�v�����9\������
+h�{!��a��|�� endobj
-15 0 obj
-<<
-/Type/Font
-/Subtype/Type1
-/Name/F3
-/FontDescriptor 14 0 R
-/BaseFont/SFIZFA+CMBX12
-/FirstChar 33
-/LastChar 196
-/Widths[342.6 581 937.5 562.5 937.5 875 312.5 437.5 437.5 562.5 875 312.5 375 312.5
-562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 312.5 312.5 342.6
-875 531.3 531.3 875 849.5 799.8 812.5 862.3 738.4 707.2 884.3 879.6 419 581 880.8
-675.9 1067.1 879.6 844.9 768.5 844.9 839.1 625 782.4 864.6 849.5 1162 849.5 849.5
-687.5 312.5 581 312.5 562.5 312.5 312.5 546.9 625 500 625 513.3 343.8 562.5 625 312.5
-343.8 593.8 312.5 937.5 625 562.5 625 593.8 459.5 443.8 437.5 625 593.8 812.5 593.8
-593.8 500 562.5 1125 562.5 562.5 562.5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 675.9 937.5 875 787 750 879.6 812.5 875 812.5 875 0 0 812.5
-656.3 625 625 937.5 937.5 312.5 343.8 562.5 562.5 562.5 562.5 562.5 849.5 500 574.1
-812.5 875 562.5 1018.5 1143.5 875 312.5 562.5]
+27 0 obj <<
+/Type /Page
+/Contents 28 0 R
+/Resources 26 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 25 0 R
+>> endobj
+26 0 obj <<
+/Font << /F8 15 0 R /F26 12 0 R /F27 31 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+34 0 obj <<
+/Length 2593      
+/Filter /FlateDecode
 >>
+stream
+xڕYK�����2�DJ��,���f�H/�,��eɑ����v�,ɪ�^�n�����^/��&��Ee�ҩZ<��G;�w���?ٺ6�?���]�����q�����x�R*,����O��UG&6�}�����h�m�k7e�����h^��1CHۣ����S@W��YkT��X��.�D����� a��8N����\���E�[T��$L���e�y�g��г��PG��Wga뜮���+��U��{���St+3�<�P.u��ƎNK�~X�1ف's�wג�Cw�W����A�p+�<���2�oXam�G)�e%�+��ﯼ]>�,鳗RBo��,+��a�H�2�I�F�UF�K.Ne�����1L��f0�5�F�a=�>���6�[�J`?Cj~�w4S�DN),cEp�T���-97Qo����Q�qp�8XG��<@��Zx]� �ݎ�mO�6�@1-/Q���y؃��I`��Q��Cv���2���V�ڒ����2�	)]͜�*+x��18?���rZ�����,a�%������ρ��(��ID˞�u�x?>��C�2JE����xꙸ�E.9~�������p��'��оz�]�I�]�x����W�B`�+�n%jK!���7\s��
+�R���-��`!�����PH��p�8E�.���dń�\t2���'�x����"�!�%���t�{��7O�s!0u�<v���F%H
+v#�q�S�����,yv�X[�*)������ޒr�Kg�75�SPG�B�3��+Uٲ�mi�(��� G�0�q�����5ܧK��ʲ,�cfVhp����2=,I������Z�^-�O��Vv\�Fgcum-�El�V�PaVx��8)\գ��ݹ�f֨��l��I�O�)xZ��+����po+y|4z˝���+���y��b���Go�pY��A3�-����D��G���A;���x7��i%9l&�O�]���5\�x�Q�*���'��d�����_n"��j�Q��B/7
+z�$ױ�in��ˋ\y���П�_�a�eΓ0_Gx6i6�&U����P��:̕�,f��`\Sɘ�&.
+pW�N�)�4�9ao���:p����TP�g��͸C�������u�t���t������+��ndstream
 endobj
-18 0 obj
-<<
-/Type/Font
-/Subtype/Type1
-/Name/F4
-/FontDescriptor 17 0 R
-/BaseFont/XCHVXE+CMR10
-/FirstChar 33
-/LastChar 196
-/Widths[277.8 500 833.3 500 833.3 777.8 277.8 388.9 388.9 500 777.8 277.8 333.3 277.8
-500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8 472.2 472.2 777.8
-750 708.3 722.2 763.9 680.6 652.8 784.7 750 361.1 513.9 777.8 625 916.7 750 777.8
-680.6 777.8 736.1 555.6 722.2 750 750 1027.8 750 750 611.1 277.8 500 277.8 500 277.8
-277.8 500 555.6 444.4 555.6 444.4 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6
-500 555.6 527.8 391.7 394.4 388.9 555.6 527.8 722.2 527.8 527.8 444.4 500 1000 500
-500 500 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 625 833.3
-777.8 694.4 666.7 750 722.2 777.8 722.2 777.8 0 0 722.2 583.3 555.6 555.6 833.3 833.3
-277.8 305.6 500 500 500 500 500 750 444.4 500 722.2 777.8 500 902.8 1013.9 777.8
-277.8 500]
+33 0 obj <<
+/Type /Page
+/Contents 34 0 R
+/Resources 32 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 25 0 R
+>> endobj
+32 0 obj <<
+/Font << /F27 31 0 R /F26 12 0 R /F8 15 0 R /F14 37 0 R /F7 18 0 R /F18 21 0 R /F17 24 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+40 0 obj <<
+/Length 2497      
+/Filter /FlateDecode
 >>
-endobj
-21 0 obj
-<<
-/Type/Font
-/Subtype/Type1
-/Name/F5
-/FontDescriptor 20 0 R
-/BaseFont/GCOOBE+CMR7
-/FirstChar 33
-/LastChar 196
-/Widths[323.4 569.4 938.5 569.4 938.5 877 323.4 446.4 446.4 569.4 877 323.4 384.9
-323.4 569.4 569.4 569.4 569.4 569.4 569.4 569.4 569.4 569.4 569.4 569.4 323.4 323.4
-323.4 877 538.7 538.7 877 843.3 798.6 815.5 860.1 767.9 737.1 883.9 843.3 412.7 583.3
-874 706.4 1027.8 843.3 877 767.9 877 829.4 631 815.5 843.3 843.3 1150.8 843.3 843.3
-692.5 323.4 569.4 323.4 569.4 323.4 323.4 569.4 631 507.9 631 507.9 354.2 569.4 631
-323.4 354.2 600.2 323.4 938.5 631 569.4 631 600.2 446.4 452.6 446.4 631 600.2 815.5
-600.2 600.2 507.9 569.4 1138.9 569.4 569.4 569.4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 706.4 938.5 877 781.8 754 843.3 815.5 877 815.5
-877 0 0 815.5 677.6 646.8 646.8 970.2 970.2 323.4 354.2 569.4 569.4 569.4 569.4 569.4
-843.3 507.9 569.4 815.5 877 569.4 1013.9 1136.9 877 323.4 569.4]
->>
-endobj
-24 0 obj
-<<
-/Type/Font
-/Subtype/Type1
-/Name/F6
-/FontDescriptor 23 0 R
-/BaseFont/DMIVYN+CMR6
-/FirstChar 33
-/LastChar 196
-/Widths[351.8 611.1 1000 611.1 1000 935.2 351.8 481.5 481.5 611.1 935.2 351.8 416.7
-351.8 611.1 611.1 611.1 611.1 611.1 611.1 611.1 611.1 611.1 611.1 611.1 351.8 351.8
-351.8 935.2 578.7 578.7 935.2 896.3 850.9 870.4 915.7 818.5 786.1 941.7 896.3 442.6
-624.1 928.7 753.7 1090.7 896.3 935.2 818.5 935.2 883.3 675.9 870.4 896.3 896.3 1220.4
-896.3 896.3 740.7 351.8 611.1 351.8 611.1 351.8 351.8 611.1 675.9 546.3 675.9 546.3
-384.3 611.1 675.9 351.8 384.3 643.5 351.8 1000 675.9 611.1 675.9 643.5 481.5 488
-481.5 675.9 643.5 870.4 643.5 643.5 546.3 611.1 1222.2 611.1 611.1 611.1 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 753.7 1000 935.2 831.5
-805.5 896.3 870.4 935.2 870.4 935.2 0 0 870.4 736.1 703.7 703.7 1055.5 1055.5 351.8
-384.3 611.1 611.1 611.1 611.1 611.1 896.3 546.3 611.1 870.4 935.2 611.1 1077.8 1207.4
-935.2 351.8 611.1]
->>
-endobj
-27 0 obj
-<<
-/Type/Font
-/Subtype/Type1
-/Name/F7
-/FontDescriptor 26 0 R
-/BaseFont/MAMUVX+CMR8
-/FirstChar 33
-/LastChar 196
-/Widths[295.1 531.3 885.4 531.3 885.4 826.4 295.1 413.2 413.2 531.3 826.4 295.1 354.2
-295.1 531.3 531.3 531.3 531.3 531.3 531.3 531.3 531.3 531.3 531.3 531.3 295.1 295.1
-295.1 826.4 501.7 501.7 826.4 795.8 752.1 767.4 811.1 722.6 693.1 833.5 795.8 382.6
-545.5 825.4 663.6 972.9 795.8 826.4 722.6 826.4 781.6 590.3 767.4 795.8 795.8 1091
-795.8 795.8 649.3 295.1 531.3 295.1 531.3 295.1 295.1 531.3 590.3 472.2 590.3 472.2
-324.7 531.3 590.3 295.1 324.7 560.8 295.1 885.4 590.3 531.3 590.3 560.8 414.1 419.1
-413.2 590.3 560.8 767.4 560.8 560.8 472.2 531.3 1062.5 531.3 531.3 531.3 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 663.6 885.4 826.4 736.8
-708.3 795.8 767.4 826.4 767.4 826.4 0 0 767.4 619.8 590.3 590.3 885.4 885.4 295.1
-324.7 531.3 531.3 531.3 531.3 531.3 795.8 472.2 531.3 767.4 826.4 531.3 958.7 1076.8
-826.4 295.1 531.3]
->>
-endobj
-29 0 obj
-<<
-/Filter[/FlateDecode]
-/Length 2118
->>
 stream
-xڍXK����f�j�%-��틛|���&�u'�7��QE�>����|2��e�Z(B��|�y��=u����5���U�e�ϡ���'T�ɲ�ﳉΕ�>[��J��Q|����}6V�s�+���ޟ'�jJܞ�v�Y�B�������;��Ī�Mw�UJ�d{]��L~*rB�N(�R���c�fYt����σ��G:qܿ�l��d�C��^���x���2���-������
-�y<�h;��������Y�>)�S7Y�aC��l��`đ�'������A�k?J��wų��$>�����Y���5�tsp���=(l����LX4�-4I��(�/ģg6!Q�}���yt�O|x<E6ꨋ\=.a''�D��dj����>�uÂ-<�=�yCw�WvnXKV�d/��yڎ�,��e��x�_ܼ��85����b-vb�Z�Z)�C����7�q}�ލ!Qh���e,�ZlG�N�)�$�Bx�-�ԅ��`X��@"./��"���/����ۈ@0Gno).�J �]�#�@�_�J����%���02�@��n@b��ih�5���.�8���˹����������I�]IC�m�a�@Y���k�^�lw�1��VP�f�Ӓ�/ɤ}�u����΂!������}rs�I���$�ݹ1ԭbue홆!MZ�-�W/��k#�t����%���O��>qPL#�O�P-	�1�ndstream
+xڭ�����1�l����Eoj+�DB$V @��i��{�����������=��I"�P����06�ȏ�T��̗�{e���Oe����g�
+<�,�L���}�&�"1:�̔��b��LgZ���W���+omW��(�����d�*���EГ�	��M�����i����)����!��x��HK�운np+*�Gfc�K�o�WT�U����!~�Ǝ�<ǭ8����
+H�-��T$��I-���W?_3�,H����7����w��-����b��ȃsNж&����D����p��Z�XfϬ?�};�|_=��H��i~I��U0��+�'�2�o3gr(�u Um��xv�5�`��������M��[R�<�R�8����4�i=����>c�E/B<ͩ� K�]�·v��Ax\�C�� �&%w��)6�hZ��1x�������(8����V1jQm�E��Pi������+�1���BJ-��/����z1���� I%�21p2q������y{����3���>��V�a�dg@˜+*�4�=6�W[�nGXl���+�qoy�M����OȊ��l���z��������B���U����b�QT*�����\d��|����_�]��
+a$|?����PHb��U����t"p'�����&F�=L��9�P�bզ���.��j�R�?N
+�U�/8�xjw��֥0���+��\r�=Fɰ9r�
+�k�����n����d�X>A�D���R,��� U��S���p�<Nj�С��F~�6�Ž�f��v`�
+�;/y��9ȩ��V��ZYs͒���|r�i�|��T�a
+�k[��v�V,����S����U���C��M"F$�P�P`T>��(�1�(H[߄5�Զ�����lb5/u�p��[�ɛ7.���2�����l��+�J�c�Z�C���=_4�"�cX�W(��$��+M�φ���3hmb�"L=�c{[���f��A+l������w\���}`c`�n�6!��	�\�rTw��nH�p��}�&m�ț➷Ȝ�~���:>�@'=�[�-�Ge�8]�.dK�%뎥%cr�q���������6�5��9�(�$`��5����ȶe��d�җ��u$�����grNl��
+	�m��(����i^<^@�����R��t��tD�y�Ŋ�)�[HȒO����7LAF ~�c��\^k����r�t�n�<b���%v$��������|�c56z�I�w?�}[)@�o��	!%r&Bccb��?$���-�endstream
 endobj
-31 0 obj
-<<
-/F1 9 0 R
-/F2 12 0 R
-/F3 15 0 R
-/F4 18 0 R
-/F5 21 0 R
-/F6 24 0 R
-/F7 27 0 R
+39 0 obj <<
+/Type /Page
+/Contents 40 0 R
+/Resources 38 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 25 0 R
+>> endobj
+38 0 obj <<
+/Font << /F27 31 0 R /F8 15 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+43 0 obj <<
+/Length 2117      
+/Filter /FlateDecode
 >>
-endobj
-6 0 obj
-<<
-/ProcSet[/PDF/Text/ImageC]
-/Font 31 0 R
->>
-endobj
-36 0 obj
-<<
-/Type/Font
-/Subtype/Type1
-/Name/F8
-/FontDescriptor 35 0 R
-/BaseFont/PQEIII+CMTT10
-/FirstChar 33
-/LastChar 196
-/Widths[525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525
-525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525
-525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525
-525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525
-525 525 525 525 525 525 525 525 525 525 525 525 525 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 525 525 525 525 525 525 525 525 525 525 0 0 525
-525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525
-525 525]
->>
-endobj
-37 0 obj
-<<
-/Filter[/FlateDecode]
-/Length 2329
->>
 stream
-x�XK����QڌD�s	:��d�c`���Y�ίO�(���Q��X������|��B��;xy��ۦZe������(�֌����q��52���.�0�����iQ�<l�q��ukR_Xm����B��?������*X�- >�r�
-0���B��L,ܭ�@�����e�m����k���	ה"����.��q�������a��D�+3�4��)0;�'�V���8�c�x>U��<��3M�8���(A�\�ڧ%�ߘ�f^R
-�A`�����%�����O�?gtNH�#��)�u����y4����D@�ɯiL%�pn���tGHD��)vT�-����/*RX�sw���H���q���,!<_gX�����ʬ�y�aҒʁz��C���(��#�}jS���-
-����+Q��*kK(�-�U�i���dgq2�9��z"X�z�e��g�G�
-�)�M�Оr�ɝHr.}��]ӞP�����s�-)����{L��������W��te�P���}�ԺJ����t�Ku�W�	ށ�䋃/UE����ċT���? ��p�D%��#�$���r�~��"rpb�KdCKB�3�����������#�q�%��]π$�LQ�����.w1e
-~S�)�,�.�M��X%�n-Q�<Y]	���!��8$Z���߮P��跩��)-��v��8ߥ���q"��8"���p~h��1��u�������tŢTd�Z�0ܹ�-���'��,�6������,��+s��YC6?����1
-�[��iȿ�ƒ�e�S�����Z�/��V5���(f����%��a�Rn��e%����/��T���\#����n�C#���)���mB�¢P�6��*rd�U���k2/����&\=8��W�k��.��|�����m3A~�X��_������D�B��I���8�P9��J��^3�9���9wÙt�k��4�����Z�LυI�:�W�|���.e��-[��S�f�ʺ���*���,Q��A�w���h��$1[5w3��6+�Q��FJ|��,�x�*2�i����ǐ\P�PQTZ�+��Ǘ�~���N�=�[�����u_�C��/T�K���ndstream
+xڭXKs�����0�l��'��cijI*ES��EjHʲ���}��+{@���
+]��U8�E�`8[��"o���ʗ��2���몾(_�[ge��Yپ�+��c)E��]\��������0���~?y��{��C���Bc_���+�"y#9��v�����C�h~5R��5��w%��HZ�
+4���+PY�ӌ�'bOLJ��Y���������k�g�ȅQ�{�iR�7��U�Z�֛�.yn�/W}�T�1��'3)��/�����%�����k��H�E�q^_{�By�H��� �z�.���|�GcOG���n�r�L�>���75|E��m���c�ʍ���K�>���3���|�%��F���kE@��
+t��XZ�sPrL7���S��\m����6��k��Z�;Ǔ������5rlP �����"m�s���Ta&=�S�yD)��b�g`yQ�^HJJ+���JK�$�9�][h:iR�g���[��9���4ۺւ��e�9oh��pw�����;���5n%�%�s����A�R�zV]�9V�����⯮�uBaT�L�I^v\M��D*��l��P�Ti�dX�[U���9hn)_���Wx�^�r����M%iV'@7(m]x�j����<!�����ΈC��Y����[�Cx%t�Td��v9�+Mu!�A��=��s�X���g[.��`W�Ƥvh������1� e�E�.�{���T�QA������B-���3���T(	TL��+�d��ZzSRo�G
+5�+�zd���P�#s$5����Y�.W*+�n=��q1�~�;��ˣ?]<�C�cCM�n�����=��J��j�On'���KG�3}����D!�����Һx��P��;�y��&���a�&f�'/:��k��'φ��yߏ$
+!ip!�endobj
-38 0 obj
-<<
-/F4 18 0 R
-/F3 15 0 R
-/F5 21 0 R
-/F8 36 0 R
-/F6 24 0 R
-/F7 27 0 R
+42 0 obj <<
+/Type /Page
+/Contents 43 0 R
+/Resources 41 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 25 0 R
+>> endobj
+41 0 obj <<
+/Font << /F27 31 0 R /F8 15 0 R /F26 12 0 R /F14 37 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+46 0 obj <<
+/Length 1692      
+/Filter /FlateDecode
 >>
-endobj
-33 0 obj
-<<
-/ProcSet[/PDF/Text/ImageC]
-/Font 38 0 R
->>
-endobj
-43 0 obj
-<<
-/Type/Font
-/Subtype/Type1
-/Name/F9
-/FontDescriptor 42 0 R
-/BaseFont/NENDNC+CMSY10
-/FirstChar 33
-/LastChar 196
-/Widths[1000 500 500 1000 1000 1000 777.8 1000 1000 611.1 611.1 1000 1000 1000 777.8
-275 1000 666.7 666.7 888.9 888.9 0 0 555.6 555.6 666.7 500 722.2 722.2 777.8 777.8
-611.1 798.5 656.8 526.5 771.4 527.8 718.7 594.9 844.5 544.5 677.8 762 689.7 1200.9
-820.5 796.1 695.6 816.7 847.5 605.6 544.6 625.8 612.8 987.8 713.3 668.3 724.7 666.7
-666.7 666.7 666.7 666.7 611.1 611.1 444.4 444.4 444.4 444.4 500 500 388.9 388.9 277.8
-500 500 611.1 500 277.8 833.3 750 833.3 416.7 666.7 666.7 777.8 777.8 444.4 444.4
-444.4 611.1 777.8 777.8 777.8 777.8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 777.8 277.8 777.8 500 777.8 500 777.8 777.8 777.8 777.8 0 0 777.8
-777.8 777.8 1000 500 500 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8
-777.8 777.8 1000 1000 777.8 777.8 1000 777.8]
->>
-endobj
-44 0 obj
-<<
-/Filter[/FlateDecode]
-/Length 2104
->>
 stream
-xڍXK����}������$���s��[hY���.UU�"�QA�p��� ɣ,�U����I��t��ey��[������@r���۲�U������Pf�����>�-�5Y}X5Y���h����Y.M�:a�#�K���Z���s�f�/V5�g��i�zX�ex=��"	[:*�����BDž-(���6�2�v-�����%�����7iQ+Q����|n���:E�'&n��i]���h;�����x��Aж��h�����O����S\��Niϛ�L���gL�Fu_����}��Ygއq��ʨ�P[g�ʢ���\����	����L����73�N9��J���VxA����*�GMŔi���Զ�4z<ڶ�B�L,\a�P�ŭ�����d��e��Kwװ?��s�1����#�US�I^�>c1���
-�k)M���0���O�@y#���EJ��3l�����b�d;�^6ex��}p�f�NZ�N�>�w�Ą�M�eZ�Ryb��	.�$|��WU��
-�ܶ�"�w��9/��.X��M_^Ij�}<�F-�Ѝ�����Ox�Ŀx+��	�z|>R{�[���S��W}�-�[I�j`L�S!&��<�	�8���y}���6	���@Req|sJBV
-ڱ����-�3۱>�|���WX���V���@,^q��������,ͯg�E�@XO��a���+�Jx��1�i��Ym�������T��r\(�-8RJ� �r	l[nk-���")ѰXWi���o �M������������L���¾�Q��o�$6�޲�d�Px�1M��c�<y'U��lc�T8OU@h���*��݉��>Tķ�%���g7Y�������ނK�v�I�^�^��{����9��@�O�ۀ������-endstream
+x�XKs���z�:��u�Ӧm�V&��X�$�)R)���Q��3irH���}�0�L��ʓ|2_M�+��T�"*������W��q��d���Zw�M?fxe��yMfqVY��d��x^ۮ7
+3�{���������qQ���o{^���v����h���[[k��,�꽤���3I��]����殮��E$�t�Q���;GdI��9�e�r�tC��`��4)����I�
+:��x�꧷o��a�����Le��*�R�ںg"�/��H�}��Bu��vi:L�,�>�O�e�߽m@ٷ;b�,�#��l���i����!b�A�a<���A��d�`+g�@=���8����iZ��8."wZ����
+8�º��<څv�{^iw���=献�����|�G�p���@�S9cψ1���z��T��.�j�B���3������>x���Ζ3ءb�ښQž��G��N�-��8���֢c�=��#V���+�^8�0+I�����<X;�I8�+�v���GϿ���p-V��<�]��d'�칲���?�I�y�1��QR	��T �l��V��E�.���O�f�+FIQ|�i}��u0��7����W[�jAUu��qf�Z��7n��|�;�ܟ~��y�i���) Q�W�����Kݏ�6�����O�����b�8��<��V�������Ay�U	�4���2��
+�C�endstream
 endobj
-45 0 obj
-<<
-/F3 15 0 R
-/F4 18 0 R
-/F9 43 0 R
-/F5 21 0 R
-/F8 36 0 R
-/F6 24 0 R
-/F7 27 0 R
+45 0 obj <<
+/Type /Page
+/Contents 46 0 R
+/Resources 44 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 25 0 R
+>> endobj
+44 0 obj <<
+/Font << /F27 31 0 R /F8 15 0 R /F26 12 0 R /F14 37 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+49 0 obj <<
+/Length 2359      
+/Filter /FlateDecode
 >>
-endobj
-40 0 obj
-<<
-/ProcSet[/PDF/Text/ImageC]
-/Font 45 0 R
->>
-endobj
-48 0 obj
-<<
-/Filter[/FlateDecode]
-/Length 2186
->>
 stream
-xڍX��-��y&���m�{��Swn����O��}�E/AA������ŏ���8Xl�a�x�
-8��j��	�����A�&n��`����:uW�y�c�m~Z����HV��B���"�W%�����(�:.W������֩�5º�%R�-}�}��H8l��\�G:�
-5]y���nZ�FI^�<����z�����������<X:��-����O{�II���v_�$�imE��Q�,�9������O��F�M���9���e�j3�̈ sVu���$��<3������S&u���t�j����cW��F5W�əppP;ZI�RW�S�%9���Y'�_>�i�w��w�ν�G���ҧ������DK�ZE�;��]��N'���]�X�`��N��u�ˮ|Gc-Tp�݈o��q'�sB���h�K�˛V��BY�
-	L���8Ouu�������s����+@�������8�//�juLj��ODk���yWW]�]!�Yx���RB;>��:����-��U[��iK�uKB������s�R��,�-& ��F���i+��z�qA�ɤ�-�ATo��b
-Bl�V��т�g�Nqs�Ŋ7y	�����-q�����ͮf�������5�.?u�8��v�Y	IK�䕔x���y���������f��	ջ	����g;��[���m�	̯��QG��ܥ�-Ά�=qI%=l��H�-%�Um2!�������BL)9�Ht�/����ʅ�#cn�:��~��}t
-�l2��r#&�
-?f!T
->�"�8��W�^S��&n��_o�|���G�i��i�#��[����xS��4�8<ȳ�5�l�m~��_W���d��p���bF2�������3�Z��:�wU���Z3���V����-endstream
+xڭY�������G���c���f:I&C��ʼnD�d_&�{��\_D`��X+\���Wv��6��z>
+�����P�S��a�H�MY=������;���*��o���v�fb���;e��e�{�>�Mu��M��ֳ
+"Ͳ���GO�j���ݞ��i�A��p�F,�Y>��J_]�n'�����+16J�/��+Z�m�ϮR����І����+C����)C g�ਈX���3&�������ȴ8��.QQW��-�x<d�g@B9��P�&F+��u�ij!���I�R�ǞT��&lXؘ.r;
+1)�G]�ԃ�V&�l
+�*D����L6[��b
+�AAf�m�r���A+ߏ���؋��<�`?2�a��q	��w���lZp/%�M��C(mÜe��:D+��E����I��-aO��+<��$z�+B?���a6p��\�0��2I�9�e��V�8��/Aۆ��e�(ߜ_��cf����V�&��e(��q�7P�D+/���V���d�4���aU��+�}
+��8k!�A,�U�[�����i�&��R���h[#���k�����lw�JF�P!l��?b@�(���>-�p��{X��H�x��uw�|4�����^ B/�^yȣ+!���4�T�U���x�v���{S�FIWC����������蜖�����y�P�@<��)�^��G]`��{a����X�y"�<�Y��endstream
 endobj
-49 0 obj
-<<
-/F4 18 0 R
-/F8 36 0 R
+48 0 obj <<
+/Type /Page
+/Contents 49 0 R
+/Resources 47 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 50 0 R
+>> endobj
+47 0 obj <<
+/Font << /F8 15 0 R /F27 31 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+53 0 obj <<
+/Length 1738      
+/Filter /FlateDecode
 >>
-endobj
-47 0 obj
-<<
-/ProcSet[/PDF/Text/ImageC]
-/Font 49 0 R
->>
-endobj
-52 0 obj
-<<
-/Filter[/FlateDecode]
-/Length 1949
->>
 stream
-xڍXKs����E	��l�g����j�K��H
-�=S�
-Pe'>h4诟�a8��߳����L��,�g�������/���Ž�+=_���4xS�E�����̃mY�&��w���˟g\2>[D)˅9�*��H��д8�A�{<��ǝ�>��o� )<bYd�,�p�#8|������4h�2���OIˢ�B�Q'\p[{:��rF
-\\��j��!(��@E���g��P4ʃ���ԍ���;��7>�Z�j��]M�W��i���p�����=ъ5��,�!����"��&B�#�:�����`pH�0F���-J�A�"�1u��:a�M*�tI��Kq#�����������q�f��]��)\2badY[�p�-��@4�FJ��Jw��lfB7���L�k��	��S+(U�ِ��o�������5}OK �#J�U=	�5)��E$�vA�Kn��H`�b�FլU�m�������4�AU�-ͮ�MG�0`��_a8��)�c�������J���
-=v�*��|�杈;����l�����|�8���C��-�+3�-endstream
+x�XKs���7j��_��M���	[S�
+�R�2�dz�������g<�dA��0!�$N�����^����*�ן��?��3dQ�g^��6׍Y^��x":���a�����2)���@&������S_�<�^G�6i�MD>��F�����i��j`�UUDk��R�����;D�(:{��D�P^�¦>���0{.���
+��ͦ���=��G#���:�rw�2WN���S��驿*p��Ak�f�Y��W�R��;��jM����޼z��x!RL�aJ䲬 ӈ�6͒(
+��)/Kć��i������9H���;�3�U]8	�����e����B�!f�8KR�C�AQ�֧H�W��/!�O��K�o�
+��!������l�3j&A&x:T@��ư@"��b@� �HboeJ�_l-��4��ѹ�J
+���΂(��80�m�
+u|��ֿ��6c����
+�_Z�Ё
+�`�$�f̠j�]���k̊���\O��6�)p���#�4aB=�E{}��@˭��i[ɀ�(���N���{����Ŀ��N��D���0�nc8ݪ��Rt�.��\�%	
+1rf����'���D-���(���lkZ�詈#Ra�a5q4�����z��^��4��P+r?u���8�.�h`�������Uu��� Gjw
+������r���X�U?��'�4f���z��c��1�@m� %*:�Ⱥ<�d��ز1ϼ�aǨ�XOG�����S�W�H��9���j[�#7O!ZUA+�������P��pq�PQ�H�ͺugjz��_���CN���涢�Ui(\��z���T���"������Zz�$������US�0��9��������m84��K(�e6�iA���_�Y��Yt���z��c[?m��zY�=ECA����k�U\@�AH���=ӷ��ˁ.r��É�H�6n d�,���B���̗0%�H��l����̱mJ������N��npt�$�!�ޫ`{��q��qB�x�|]4���=��'+��P�������������๧�Bc��JHw$J{"�+k7(��N('>���k'׍�S����#�?!n�3.��nV� ���(���/����endstream
 endobj
-53 0 obj
-<<
-/F3 15 0 R
-/F4 18 0 R
-/F9 43 0 R
-/F8 36 0 R
+52 0 obj <<
+/Type /Page
+/Contents 53 0 R
+/Resources 51 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 50 0 R
+>> endobj
+51 0 obj <<
+/Font << /F27 31 0 R /F8 15 0 R /F26 12 0 R /F14 37 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+56 0 obj <<
+/Length 2234      
+/Filter /FlateDecode
 >>
-endobj
-51 0 obj
-<<
-/ProcSet[/PDF/Text/ImageC]
-/Font 53 0 R
->>
-endobj
-56 0 obj
-<<
-/Filter[/FlateDecode]
-/Length 1880
->>
 stream
-xڵXYs�~���I��C;I�&�Z�>ԝ,�&�����δ/"�X,��?f�3��x�����%��ƳE����a�b�lw;_DZy��V���u���)�V���vEa���fJ�?���n��ثP$� )�u���<W^%�m���?����Y�����];��׮F5s��&��ߒ�J��+�u#�R����/�nj��{\B
-i��ݭ+��Ӑ[������wݹM���U�����qM����'��Bҽ�ę�����TiW�-D�lm�:/��9g8��|T���`%"�-f�A5�YHn�QyuՕŢ�ݎyZ��t����M"=���!�>�Ct�	Lo`xn�ڴ�*b���Ƴr�CI�ȰX��ME>�>����ʘ������"�T��A��-�<��r?�����׃�Cɰ�ny=
-��-#����<<eV��y�T���+�cc�������e�LR\���RNv����8}���t
-��a5�A>�(���@>��&��0%j��v�ηXԴ���;׎0��:0�)�&%&MkjR���~���k"��帇������ ��$���0)�>��.����%��:��\JH`�<O�T) ��2�ū��n�1���r���]�o޻$g;R�m�S �,v��n�@���	16Xv�k3fS�Wz��-�q�=��=W2+Cw�ej���K&���p��f����SI��x�5��O8�Ǥ��9���(��`7�5��6�)��������=����f���'��n�K�
-e�u�3P»�G�	-�4*����UҳĽ��,�	���v�]��y��H=i�����\Ϣ�<�ӕ��Bd������5�Q�<ևc-endstream
+xڝYKs��ϯp͉���ڃ���3�XsڤR�P�H-	�����
+���,�8�Zm����y�Q�FW��/a�/~]��F�k��E\xv�����~���ݾǕ�>i�G7꭬�3͖���L�k��q������עH��H<����D���UUdQ�Y�W����\W~�q���.�A����x�n0d����8�{��%
++��a��ހ�ٛ����������[3kV*J�%Q�L�e*({�6�2zL%Nf���9�_v`s���`���+?�Q^����������=k�����|�Q�'���T�n1����4����>���a���q�\���\�E�\���Q#�d䒌\��K�g:M"F��Z,��#�t�e.�e#�l䒍\��'eU}4U��[���&6;S�R�)�)6
+��J��׈1fiJ�<����ΰ��y�����l(+a��+o����n����I�4�����j�$$��E;-����ʏ—6����L������!ft��2�q�W�+�˽vÿ�:�>	5-$����r������X-
+����cqK���+�3�	����>�(�p������4�+1�s��[C�Zc`�q���L�Tv���Z��+�
+�'R�Z�&qA~$�&��E5�C��%
+�+IZ&+�����8{\��)~�R�n�r��|�6��w�H����A��Xv�K��f"�2;�`T��\Rа	X���r9#d�Q&c��+��`�R�`-p��[��*��+�+I9�2�"ͽ8�Su�ߋ�$+HH�Y͠C*D,�����zR!�1�����Ո{��O+PLs�)��O^^�,p�}��K;�������9T���i�;���f!eM�K��+�3Y|���e�+^~�^&�c�o��@rz�f��\v�3������/���^=4HBқ�{�����7�����ʽ�<����Y��ߊ�lv�n1��/>�펇��5�)�
+����)�r����~�=n��nxV9'x(�����y�!���?}}�߿�]t��Z�O����ߨ�����tws8�-M.��GgL;}7�h�[�‘�m��Uu�Ƚҁ��LhN��M����}�b^Ϥx�T�,��"LI�%�z�z���stream
 endobj
-57 0 obj
-<<
-/F3 15 0 R
-/F4 18 0 R
-/F9 43 0 R
-/F8 36 0 R
+55 0 obj <<
+/Type /Page
+/Contents 56 0 R
+/Resources 54 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 50 0 R
+>> endobj
+54 0 obj <<
+/Font << /F14 37 0 R /F8 15 0 R /F27 31 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+59 0 obj <<
+/Length 1361      
+/Filter /FlateDecode
 >>
-endobj
-55 0 obj
-<<
-/ProcSet[/PDF/Text/ImageC]
-/Font 57 0 R
->>
-endobj
-60 0 obj
-<<
-/Filter[/FlateDecode]
-/Length 1907
->>
 stream
-xڍX���a�E"�i��$K����Be�G�`����<�<�;�5slǙ=��������C�~V��nu���e1_���ٕ�;��j4ﻳ��f
-ǿ�?�k�-\׎���ʊGf*�����둊mU>���,�d���������0����	ǎ�c������6���I�<%lJ����t��;$�1��-?���������,<.��3��^x�Y�r��m���D�tT4������������i�����*"F':Ĺ|�-.�7������y��
-<[�!��=Q=�by��8���8!<��cqC�w��0el�1e��4<&��-��Yj/���9�2�rD��Q���س��kU���Jo�����T��.	z(
-�-����p�b���LV	��A��]��=}��c��˶Jt}�C$p��,T�ax9ÊH�?̾`�)�����3����G8�J�a|���?����_z��X���G�w}�o$�Q7U��wb��0���(2Q�&&�4I��̍,&�Լf�"Dч]C����
-Ga�	B�S����pt��uݰ����`�A͞����z#�K��Pl���2Hw]Z���*tapưS���Q5�D� W�x�!\���y
-�,���t��+$"F~E���<�to\��]�PjTŋM�ySv�9�1E���Jh�9���eպi���]�v-���
-�Ք���D�����JT܇
-��TԦ�^xm<��-endstream
+xڥWmo�����Zջ��%Ζ�K2�0�C�HLDD]��k�^(�4J3t�����l4����� ��t2���yA��e����̏�~�q�^�<��7
+�h4o�$!)�Dc�ֈFh���r!����T��^y��9��wB{yY>��>�d���%;��[��f��}��u�5�#����gO�ɥ9W�E�ES�Ô���_��8=Y^\]~���^��_fgO�O��Q��j��R�G�>9��h
+�H�M��;���n8q�kY��ά���W|�� vb�[ɻ
+�[��c�{;+�.S��oU��+3g#��5}��h����\��ڈ��㻡�x��J]t��pIk�8kYZw7��J��+!nqu�OySֲ�c=����˳��{�|�!k+%l�Z����Ú�6��h����?�/W���s��i
+jb�J�SZC�ʰ�qh��=ٌ�J�
+��5)�'����Sgg���+�s#����$>�'+ق��+;��^"#�E��S�k������yH����<+��6q���+r����n�bDȊ�0���S٫M5
+��;�@ &iP�ޜ�Дj]��(���+��8U\mTT���8�:}���o�v���������2巚%�w�r#� ��+c~�P�Łc[+��B�N�/(�Q��G���S�l��\0�I�s [���'����eֽ�F�w9��j!%�&��Y28 endobj
-61 0 obj
-<<
-/F8 36 0 R
-/F4 18 0 R
-/F3 15 0 R
+58 0 obj <<
+/Type /Page
+/Contents 59 0 R
+/Resources 57 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 50 0 R
+>> endobj
+57 0 obj <<
+/Font << /F27 31 0 R /F8 15 0 R /F26 12 0 R /F14 37 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+62 0 obj <<
+/Length 587       
+/Filter /FlateDecode
 >>
-endobj
-59 0 obj
-<<
-/ProcSet[/PDF/Text/ImageC]
-/Font 61 0 R
->>
-endobj
-64 0 obj
-<<
-/Filter[/FlateDecode]
-/Length 1744
->>
 stream
-xڽWKs����fL�@�j��$m�ig��D��F�,�%R%);ί�>$��������Aήf4�v1[;[�g�
-�[$����j��ϗo͑�Ɛ�?V��̐4g��8����p���$�W��Ֆ	{R��[\F^���������#q�h��E��|����y2�K8l��w�O?�A=��3�M?���M�8���y���n3Oq�y��+j�j��m�8���t�F*G�r�n�ҹMGf��&t�;ӹͦ�����M=��c�t�=�X�٧�퓫o�HT��M�,������* �i��BN�
-��7E����r�z���PŚSw�����Y1��5���a�CS�W<=Ƅ��������!x�=�@Ç-P'a<4����v����������ee�86��3��-�Qmb�ndstream
+xڭT;��0��H�m�E:��k�R$)�,ˢ�k&w���i�of���e�q��<�N�L�����X�L����>��[�L���s(EFR\���k��\x��C�n������E�
+�'�9��P�Q*]ƙ1ł�7�e����27�C� "����"��!S��,����X�*�+��u���+���p���?�~+b������8B�?�1L�&�X�(����4\Z8$��S! ���d7�\���E�D���}X�0H@�&�����՜o۴(�-xZ��}�+��������h�/*'oG�.��jq�K<��k(����sWI�@,�iԓ.����+��Y=}xZy�y·a endobj
-65 0 obj
-<<
-/F9 43 0 R
-/F4 18 0 R
-/F8 36 0 R
+61 0 obj <<
+/Type /Page
+/Contents 62 0 R
+/Resources 60 0 R
+/MediaBox [0 0 595.2756 841.8898]
+/Parent 50 0 R
+>> endobj
+60 0 obj <<
+/Font << /F14 37 0 R /F8 15 0 R /F27 31 0 R >>
+/ProcSet [ /PDF /Text ]
+>> endobj
+36 0 obj <<
+/Length1 750
+/Length2 576
+/Length3 532
+/Length 1110      
+/Filter /FlateDecode
 >>
-endobj
-63 0 obj
-<<
-/ProcSet[/PDF/Text/ImageC]
-/Font 65 0 R
->>
-endobj
-68 0 obj
-<<
-/Filter[/FlateDecode]
-/Length 1567
->>
 stream
-xڥW������v����6���DۼʢKQqr�#��� 	�� -�Z��.Y��<Z�Uc�^(�V�|���[�ˍaoG���Lm���%T7�?�ܙ[���ҫ��1���2��}k#Q�ڡ~�������\;�׼H%N���L�������ޞ���$��;S�T*�j"-�?L�X?��0���B������kʵ�W�<<l�/s$��Z�����j�*�$3�e��r�*�����{�wh��=�6;��tO��L��*}u	����͌�ʆjE�*-�l�˵
-A7���H����|�k���嵦���\�Hs��bÒXP-�5�v�7}���ì��S��\�o��@頦'
-� ��-i>��o
-�����C&=v��ءKj@d�ߵ�
->���G�v�Wɚ�K&�&�h�ٜ?dLqx�}�|L1ij��-B�-��o�-���~����;�H�ű���2cJ�²Z���~��"����#J�($mj��#^��P#�>gl����5/@3�_�	cx�a�Ϥ��~�����#��Y���-endstream
+x�U�L�Ju�+���Rp�44P0��u.JM,��I,I�R0��4Tp,MW04U00�22�25�p��,��Q��)2Wp�-�N��H����������ZR�������Z�ZT����h����\������ǥr�g^Z��9D8��+@'��T*���q�����B7ܭ4'�1d<8�0�3s*�*�KR�|���B盚�Y��.����옗����kh�g`l
+��vˬHM	�I�HK�N��楠;|`����xkC����WRY��`�P
+���P�6�00*B+�׼�̼t#S3�Ģ��.`
+�
+2�R+�.��/jQ+���$e~s�ʻ���?��|<ċݺ���'}I������xT.��gt���vՏG��U|���~��]�_k��{��
+�}dN<6�-uB��H��c�M�H���q�a�K�K̞�}��˛���m����o���v�
+���s>���.#��ߦ�{�/��kܗ<n��[�����[����d����1���͓_��aՍ-<�+{f�#Mz���=��Y���/�T�}���)���0��:o�K���.l���yE�
+���צ������_��	�ᚔi�s�`��C���I^>�������d�j|��/�p�0,H�M,*�M,� endobj
-69 0 obj
-<<
-/F4 18 0 R
-/F8 36 0 R
-/F3 15 0 R
-/F9 43 0 R
->>
-endobj
-67 0 obj
-<<
-/ProcSet[/PDF/Text/ImageC]
-/Font 69 0 R
->>
-endobj
-8 0 obj
-<<
-/Type/FontDescriptor
-/CapHeight 850
-/Ascent 850
-/Descent -200
-/FontBBox[-33 -250 945 749]
-/FontName/XEEAJR+CMR17
-/ItalicAngle 0
-/StemV 53
-/FontFile 7 0 R
+37 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 63 0 R
+/FirstChar 15
+/LastChar 15
+/Widths 64 0 R
+/BaseFont /NTVDHS+CMSY10
+/FontDescriptor 35 0 R
+>> endobj
+35 0 obj <<
+/Ascent 750
+/CapHeight 683
+/Descent -194
+/FontName /NTVDHS+CMSY10
+/ItalicAngle -14.035
+/StemV 85
+/XHeight 431
+/FontBBox [-29 -960 1116 775]
 /Flags 4
->>
+/CharSet (/bullet)
+/FontFile 36 0 R
+>> endobj
+64 0 obj
+[500 ]
 endobj
-7 0 obj
-<<
-/Filter[/FlateDecode]
-/Length1 1095
-/Length2 4446
-/Length3 533
-/Length 5179
+63 0 obj <<
+/Type /Encoding
+/Differences [ 0 /.notdef 15/bullet 16/.notdef]
+>> endobj
+30 0 obj <<
+/Length1 1884
+/Length2 12110
+/Length3 532
+/Length 13167     
+/Filter /FlateDecode
 >>
 stream
-x��gXm��RB��H��@HR0�TC�&
-RD@��4�w���PP�#����^�2�s���s��a%���!�	iIi(�mj)�-�Ձ���4��\������ ����<<�G�X���E�`����~A�-D",P~pO���#��� �������%����Y��b{�QJRJJ�XH�����8
-K
-9y-����0�
-���
-J�oר{[������+N:dt5DMRI��cJpm����O�R9[�������Da��Qf�t���	,KU������������jgʏi>є�?���ҫy�������C����>��ȼ/�nlB��Ⱦ޺�)<�CY+f��%q���Tx�R��	�sסmiS��{�8�v��%?�5lm7r�ba�oh�㜣��]x.�W�c��͠�Y�u�U�!AY��V8�$�����)Y�3#'a��i޵d!���ܚY0�a0,��
-�n�F�E�FU������C:�ѫ3W�#��h?y>��1�_ίz�ʈ#
-�#<����D�k�w�b�8�w*�m\��"7�[�dӯ1)�0X��l�����@��F�E0��!/`��Ķ7�$��-,/��uob�����;y1�#_�k	�|I�.�©���m��H�s�����o�$���ʀ��[�t�*i7|��'�8Q�T�!�:�祖=��B~��Z���Z)Rn��i:m�����Lj��ܻ�Ź�OZ�I.��� �
-|��!L�w�mN)����fJ��٬KZr�9<QR�#ژ9s�����/����9���'����|�O��y��.�]��^l畕b�}3K�/~�i�x����i����м�P�@������t{ܨOp��-�"{Û��L�����������R.}�J?�c��H�w^B�K>��Я�{��yM�b׌�D����D�r
-j8�8MA���ج�Nݲե?=���Q"{���=�\��l�>d�S����_m]
-�4a�'y��D�8guKpqM����2%�S�����p�(�����j�3���wK�QH���!�Qg�L����&��T�����(>A<�)�6�\��U��v�P41��h��si滿�Z?�-����i|��:Z܌�s��ͪ-r��k�����<Ɓ�M^ۑŃ���k,���_�����`a嶌tQ�E���-BV7_��g�fp*��/���'u�l#'W�T�I��?>�x2c2�q�6�^Ӡ�%珔v됮��S�g�WY2��u��Pvf�\���ɓ��-���M5̣��u���,姨y}�92(��ם�[U�Ҿ�ɜ�;Ci���E���PE�C^�7�8]��)Z�� 3B����O����������	�j�n$���P;*����;̍-�_Te���bz5�����t�a�̒f��`C�0�RZ�{�Ҿ��W��6j;���;J!Q���Zݔ׾7?�B=Y���� ץ��vo���'�%�gm����j�D�����6�N��9
-�v�Oy&=�@4��d_�.�xB��
-��c���y$(���N���,��������
-X^R�,���oP���Y���/T�l����W�[fj�ʼ�L\q$��H�����:9�X�X��<v���r�iBuZ�ݡ��@��(���$I�2���v	��/h�q��k�����B����Rn����nJ�����P��n�����jI�wl����˹����V�1���F6�-,�!�ܯIY�w�8ؓ�b�j���)�\&a��yQI��Lj�E>��=k������BT׫y1�C���M���g$_�^SX̍"?�Z������.w~̲jpŀ�95F�"4��M$��a���L�ě����������(	E�%nb.�5Mf�!�%��E�26�ӊ�Y���^���!b�a�o0[�}���9'1���M0��u���Ujjt�|*}ɵ�v�;�U,�������R�i������2j{�v���,:���(��]֋�h������9�aw���ڽ��U���sw����`w廬v?$���w?���S�"����Ge�7�]��J��x^-�����.�t�jgYoXk�O��m�S���'��ڵ<�7!��SdBn�y�2��WUh���-���	�򉕪7����nv����ƒLJ�т��
-�L-endstream
+x��UX̶h��k�+��3�a0Zz:X�8��@fB�+�y0��D���gae_Lf����˿>�������H�K S���
+?�XH����o�+���ec��4[�Y��������>ʓW��	�o�nF�Y^mDZ�Y���;��!�+R�Ks���+����� zu�{�C88�$�l�C���`d8VD��o�c�$�N�Ү߀:]���
+��!�LᢃXD����6�6c�
+e=��&���5��?�fvU�z=!^�&	���g��5/�PU`�����CWK�2�����f+^+]y��;Bϕ?KCvl��OQ�"��V��؍�Y9'ôj�[J�‹1�� {�_y�S�W������bz�(�&>�� �����;���\�x��)�]����@��7�����fX�U�h��Ȝ����Vچx�*iY�V�d�Y��dn�����f�p��JW���n�XJ��+�j#V�L`a�rڥDrC���p�����'��ڰ�0�"�v��qX�9��ؾY���y+Ŋ��#������&)��7?m!?'~tdC2�~��,eS���j�\�J�������h;�+�geQ{ �n/%trT���t�4��	������0��M�|�4��J�e����LAW��\h���%������C��α0�
+������>$��Eqb;'��:�}
+���r��� ��%���k�3	�+)aq���{�����w珦J��9���N�����^10����h����D(���c=����"�\y4����T�i'�o%�e����9��5��p�Q��G��Ѥ�;;-�g���p<�>��T�p�"a��jK|y���O���9�.��+���<���#�l��a�'`o�.������mXW������+���ܙ!r�{'��s��wFtqd���gY���:~����~'�1�է]Ѯ�ĉ'��Aܫ� \L��d{JL:E��Zo��vO]l�V�0��������N���B���WI��+��HD!�q^`�����`x�S5���r�谞1�ߓN�l����`+�u�*�VQ��ֻ8�GXl2?����y��K�B�y#���65����$�������߸��+ޢ'�MsrVA� �͕�����	ʞ��+��������7_�/�R��	k&�͏�n����	ƽ�A��'Xza*
+��lm#���pϲ\!�/���ټ=|F[�7Y�DԱ�m�6������f��c;PvN���{�p��Ό�������"
+ٹ��,ݜ��l�k5���T���m^z�js&
+RX��+VD��C���/� 
+��l�%���s,J������Ȇ�!���p(�vn�v��������mJ��q�?�]2'Ng���׌1��-0Oɸt�����k�)��śni��f۹ߌ��nu�bZ'U��7���f��dK���WtЦ�`�KC�˙xW�]�װHQ�#����e�W�q�E��iY0����|*_\�Ʀj��|Ѯ��h ���������C��E�r�%}�eM��XQAGS�2~��D��u݋ou���&Rm��sID�Sb9���ߪ�G�F��e��B�0O��GZ�3H�v���ve��6&_�/��+h�
+5M�<E�둒?JY�9N�P{�n-��I$�}�+����4Ŝ@���'3s
+�(S4J�[��Q�#�L��Gq�Y���D��O7��<�+��W�����.{2z	J���o�(���W<
+q�1>4`U�+q����sp�!o|K��"�!8���܁���*�#)5�^7�v�B1��:�1�F�E\C�d��G�h#���ұP��z{�iG?\\��:�$2���GN:��l���\f5&͹n����?ڤ5H�?�9��Z���#�a�F�C?�]bF���m���%JG_�Ő�D���gxx�J�=8m�������`��7&b�!�Z�A�'����p�%e9'���������F�0������-�m�y��2	rh�
+��S��rS� �zL��l�w�	�xx������Lk� '_Ɯ����]�1��n|
+���9h���:���-Ѥ�6|�9�m�;O��E *W~�xd��CReC�c1nLq��|�HH+g��9J=�������BRK�5	�2!'ͪ���2zWL�=
+��|�W�k朦n��1“'�K7��U��a�-�W6���]�C�,<��o-���'a��	2c���$<�‚&����n��K��u�3�F�ڏ$�Jzt��S�C�p8�a2{�%�����x�^��4���-.�:PW��8U���VL�|#��P�>.*Y\�QUPrA���#:�����R��@�)�;����|��F��y�X��8zv�:���x�CS,�ƈ0����)�M7B�+��06�Q`+��\ü~� W���cб��.�;��\�����a�*ю[�[5<˻T�Zvt�?���'�?ud������;�����3��/�X2D�m>���
+ +�8�`��Ơ�Ě�}�
+�{k�;�أn��ԅy��9��"����"6��la�0�M�m.
+��:!ڕ=>ng��i�#�sW�l��/{�
+��b�ۈ`�إ���8Ֆ��T��+eq�[���
+��u��˓iz$>��в���g�K.�y�I�w�O�k��Q���v4���dp0�F�#�]
+���{�0�@-Q�ix�J���S��{�
+����������i�s�e�W����.��]�����e��5�K:f����k������6�\J�x��+�2���$�no���a+���l�`-�TVo�,A��[���a������ț	�h�(����G&/u[h�7մQ77���A��m�C�!�4��K�*��`N��ǡ������-�ʜ���a�닰�Ip{_)[m���P���̊g��L�����l��ul��������u8F�ۖm�o2�����ſM[��aˊ��U����LP-er�WJ5��s-q��ՠ<���M&��mF�l�z�G�K�?��\�+*�R$���
+�Q���b�K{�,ɣUк𼏧�(7������οʿ�=������7ϮD��W����^�=�\ׯ8�C��"] db��|h��y�%
+ṟy]�+��
+(���P��#��x����\�h�$��nT��B�Fy3"e����X6QЯ�x�m�m��?��/�9S���0؛׳��h1������������N~v����%��$����"ex�nv� �aew��]pS��-��R4��^	�:�b0�>�f����`I�mL�۲Y��`�8���g."ǝ.�g�������VL�����al5I|�����i��.]��<����,)�������k_+��.�8ݓ8��D� ۖ�p�^�n����Mr!��a�u���T�.t�Ti��\�������=٦��đn~��T��5�rO�W/�s,bV9�Q�q6�����et�������z}l򮂐�Ѽn��
+���~`m�#���*�y����ρ
+P"<D�ю�ǝ��.�>u�u���
+��_VtfA�^�:�P+��ZD!Hj��	l#�C�����������_?�������,��1*n�/��}O�΃��6��u�^�2+qʴ��l�\i��a4�Ќʳn&6��I`�^���=ȡ��N����=n~���?1z�&c���Dqm^�y01f��{u�<��E+r���&�>�kfB׮VH���܇?hXgh\�M��Y`�ʤ�7%|��nr-Rõ��X^Ξ��mF�좾tXč�6b�Ϣ;o4�F%�U�����2~؆��׭��;��r=�K���������a�I�S9n��Q�sէC�������������˳��C�ơ�¿���x�e(��}Co���%c�0��i+�%�aY�i8A?a����*l����'���G���͖@I�ɃK���BUԄ�;:�H7�tNW�R-D:���;`��mѵ:Q��+F�����"�P�uit���u��\�:S� �&��Dx��3"�D�:�Q�H�+AO�	�i��RǓBu�LW������Qpb�r~X�?S:�Y����w��+�\�b���
+<�Т,�!���6����F�y�;b��>����8�@��B��}z]����^cT��h��Jزs�&zo���a=�﷋��F��WI�+����VQ�O���m�v�\\h��<���f��A[9�(γ�?+�I��-�sc�|4�h���͗�^����L�� A�+���)̍S3c��γr�?�Hi�l9#u����ӄ�49+W��}j��}�2�I%�	���v)�^���i��.��K�G9�T� >�ќ�9��abI"����z���U����~�Aϐl����8��Ϸ�E��a/
+P�����'�yws'��ڵG��t�36(\���T�/"ᕳ/2D���[�^��eZx�U����r,�TI�]�
+Bg�Z	��Q�V2��?�{���``�ie����msbwd��Ҿv�* 8|6$�~��"u��ӗ��Ӎ+��L��Z*h����_�Ԅ�%�����+q'E��T%z����M�%y��Kq^'���D��<��J8f���}��l�n$��K�f@Ĥ��f{����R���r���j�%��ɤ�|�w����}KW�����R�endobj
-11 0 obj
-<<
-/Type/FontDescriptor
-/CapHeight 850
-/Ascent 850
-/Descent -200
-/FontBBox[-34 -251 988 750]
-/FontName/NJEYML+CMR12
+31 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 65 0 R
+/FirstChar 33
+/LastChar 125
+/Widths 66 0 R
+/BaseFont /NRYWIT+CMTT10
+/FontDescriptor 29 0 R
+>> endobj
+29 0 obj <<
+/Ascent 611
+/CapHeight 611
+/Descent -222
+/FontName /NRYWIT+CMTT10
 /ItalicAngle 0
-/StemV 65
-/FontFile 10 0 R
+/StemV 69
+/XHeight 431
+/FontBBox [-4 -235 731 800]
 /Flags 4
->>
+/CharSet (/exclam/quotedbl/parenleft/parenright/asterisk/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/equal/A/B/C/D/E/F/G/H/I/L/M/N/O/P/Q/R/S/T/U/V/W/Y/underscore/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/braceleft/braceright)
+/FontFile 30 0 R
+>> endobj
+66 0 obj
+[525 525 0 0 0 0 0 525 525 525 0 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 0 525 0 0 0 525 525 525 525 525 525 525 525 525 0 0 525 525 525 525 525 525 525 525 525 525 525 525 0 525 0 0 0 0 0 525 0 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 0 525 0 525 ]
 endobj
-10 0 obj
-<<
-/Filter[/FlateDecode]
-/Length1 1091
-/Length2 4694
-/Length3 533
-/Length 5429
+65 0 obj <<
+/Type /Encoding
+/Differences [ 0 /.notdef 33/exclam/quotedbl 35/.notdef 40/parenleft/parenright/asterisk 43/.notdef 44/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon 60/.notdef 61/equal 62/.notdef 65/A/B/C/D/E/F/G/H/I 74/.notdef 76/L/M/N/O/P/Q/R/S/T/U/V/W 88/.notdef 89/Y 90/.notdef 95/underscore 96/.notdef 97/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y 122/.notdef 123/braceleft 124/.notdef 125/braceright 126/.notdef]
+>> endobj
+23 0 obj <<
+/Length1 1140
+/Length2 5257
+/Length3 532
+/Length 5984      
+/Filter /FlateDecode
 >>
 stream
-x��g8�k�ljh�G�#!�1J0$��D�1��0F2z�� H��A0z�!�"щ�™��s����/������U���PH�(X��%�`1q-(�p���@�����.�@(�+x��w<���j���"bը����"�H�R�W�ڛ�V�ҪYjS���6U���{�����9��
+� �H7OA�X��m 		���;O8��*
+KI����0,!-*%-�M*"Q~h8�ȫ�+�E�vn@m;O'([b�4DB�?!���+��@��u��8�h��+�Z���;����ꯢ�r3�
+�	�����Y��Az�����o���$� ���e�@0��@�6u��� V�n V� �/��� V����~�������PPD\���4�����]f(�
+�"!2��u�ʅ#��
+��	:�m[HC�q]��/֘�WdҐ����7?�T�}��=ӿ�� S�
+u����n����d������=^%�/D�-�_��+��c���"��[�݀2ݽ,R,b�2�H�sq��~ҕ����+���)�I���]L��1�����Ƌ�܈hwB�۸lv���r=dz��e��s���>�bA�T��j%[8�,�r����Ա&=kS�?�2��k �#�+
+h2S��e������_m�έ�G'Y�����:{J~��@�z'^���y^)�C0�����>���y&!|�”أ��<���N�/}��pmDR�e���*��gO���v�+��p�V�WF��8�ҙ3�Y�G*�/�t{bj�~>������s��U7�g>���~ӵ0L�=�\fm���Q����ӏ����+|�e�]Ý�������S�W�:�{��ժ�b��� �V*���G�i=y�52LG�dm�r�jO�C_�~S��8Dq���h�۫�n� ��������\V�� �ٓ��#?
+���)��xKk����_@�p�g�N�~Kj�����Oe��q���2�f�������b�F2�&��b���
+L=�sOI衏4�ඈ����Ve
+�-�N>:�֨P�X0đVV��NKK�P�C�-�~M)��{m$&�f��~��71>V�̭��^#�X�7r��=��<��޳�٤�YmYΈ�J(�%�G���6��^�OIhvH\��6L�m%4�����h���l/�e�E=A�U%�� ��0B�����X�lp$���%-�Pp��lh�`�Yr[������p-��+`2�ڊi�fJU���u�ִ6�#���P�%��u������ˢ�d��ތ6�%;5
+	�e+h�����M�M�e��H�[J�Me���_c|��!o��&?גݤ����Mo������Q���������\.1��&��g:�q�2�E��^�,ns�@���:�|[��$����A���<Ix������Z�̋�:��q����[����>;>|/�2�T�M����v����X��)%�Z��g�C�.F��һ�Մ��i�
 
-G�B����@�o0��°@���Da)@BS|���JIAv(���%\
-�y���iq ��
-���G0�
-��������0��(	9�H��
-	f]~C9 �Α�!a#�(A8��
-��4��	?%�����ޢ�R@Q	B���2���5�	w�#4W\\FN����!1��	c	�aav��t&8����֑��
-����-*R�1��Pg��܊�������������5�-��z�p���5)�4���{:��-1n��]�A�k'��9� C�W��3�zVH0�όw�D��U����7������ ?h5�-�����{'��'��"���vK:MISV��J
-�~%
-Ư[f�����Ӗ���#�BR�w���q\R���(�6�������ZR	ݺ7�e���Q��#{�c:~���o��K�	�{'�;��k��<k����m�2�����z��&�~�2���-���~i���"�X���5V��ϋ���Sn,�����	�(��D@��	ϒT��e踬�F���uv��t���;���٣�f>��34�	�6��1��*�ռ?ր��*3��_�j4#�`��*�3�nL�X���n\�J�^��pӭ�U�>>\��p��t�X=n�9���4S[����C�AR�Riin+���V�+L��/���@(������,��i���{��pA�����?�����o���zCUg��w�K��l����33��#T��ul�;�_w�k��5���������^:�c��D��[J���`f�B���'�{�R4/�������[��G��MX/���͛�oqܩ� $M���N�ǵԕ���d�g�ʥ����'����������8鉧�A]{,C�%�x9�me95қZ���x�v�+�2�x��oS �-щ�@9�we���|ɦȝ�(�����t�g�}Pc�z��;�&�l.SIZf g���-�	�FnEn�Z��G�����Fw�[���U��+I~�O�<\����~�����r�^C��i��+޷��4�[2>�,��&R��y
-�i" u%� ��-�s��'�=�����-}���ߐ,x��Z��-�m+G��V�,���?��_�-�G�)_%�b�]�V��Z��Ф��v��Y%��6�Gk�O�����K�=��E2������9����~�{["����Բ	˟es�Q]���
-��F�?�����b��H�	
-�L���„q�������ɷ凂�޺�d&|QJ>���)
-�h���Ȕ���#^��m�4������3�%
-0��
-^.xɿuSw��J�=��<AD�S��-�#�⓿58sQ�Z��qZ
-h,��D���B$;����^ПЪ�r�����J�����D� zj��ޯ�.7����q<�W����TM�]���31������@�E=-�T��m~'���gn�᳾
-����p�5u��-����f<�����H�(-��,�UG�@��_:�h�y�A~�'�g����jü5�M��%��PGLda\�
-
-<�B���������������[�jf��j+��4��
-��Lz�!|kS�Y�W2�ӵY�V�[\��Kކ)K�����3T���Hٗ�v���}��MK>��~M�Y��-�]D$�5�����5�=ǹ�4�ų͑�)�����	���6Ո�[�^����5oA�n�-����������Im�����������嘺~+`?/dü��W�4��Y�$f
-��V@�י+��w�����Z!?��
-��X�9(�W�U�J�D5���W�Ur��$
-��|�Z*~��?���{���\�3�H��Y��¸B�+���gp�W��!uf�x>G9j��^�̸l��~���+�hb�gjS���]b�fT��1���v,�~By�o�z)�z�4,9�.�o>�&=��sb�o]a��T�G?�{s@v��M�G�٥�s_�ݫ;w��)r8'C�j�p��f�!G�߄q~j�1���,��G�s���4�����u܀�.��h堧�-���/i��*V�bN
-�0{Q�N������ғ�Q�����aZ����T��N�_;���9�D�J����g�X>�����y��l�_�Q����|��cWH����\�̈���/��v)z#+G{u�R��C̿��.Q�k/��3�h.f�)r��^^4��ڔ���6��������}Fr��gѕ*L�]٨Z/��R��*�����벜\W���� ��,�*�"��_ye''ݞ͚[�ڻ�9�Go�\>\sc��b
-M\_%.���N�d���0)���[����z9�X�9��+[�9�)#���K�=�(8bĨut?����µ���S�����4��ͮ��-���q<������"U��H��As�.��)�>ٯ%�j�83�L	�;�Ņ�7�UQk�@����s�����=d,�7���A��7?��=��F�L��o����IN��̭S����niY��_PV&k�-�1�g94Z�#�T�
-6����OD�v�R
-�_ٹ���D��������`��	݃�7	���P=��������>�����O3��t)v�S�3ȘQݼS�����5V^��1J��)�Ji�m�[�
-���j��!���+I=>�Ջ{	����Zkt��7b�c�J_MrH6�������69#��.x5����L�y�e�D�2v��}}e�t��n���#a�m�1��1%�d�x�Q ��-'ؿ�������ݐԕ�?"����%(��̗@ea�9�C�Զq�吧�~��q):$��ܬA���:�$�ć�-endstream
+H�_Dy]̠��\����ەl8�܈퓕{��NX���Pa�+�yW�����*�7����"�ݹD�d/L6�o�x1��Am�D,~�H����轶A�n���*���X�Z���J�CN>`��d�6�k�u�J&l'"��=�	Z;j\/P��\��bL���=ʢ ��9붤��k`��:G�M����9�����зܹ0����~�MY������o6/�y_�n��z)��U�{�s>=h���(.F�{-�z�a|$������+n�e�C����%Ga�W�����S��m(G���?C���)D2��$5b�}ȼM3��%�4鴅I�>��K,���{�D�K�R��mK�a���B$,˘�|�Ԍ�օ���]�G{ep�E��X�����T�w�������� {x�'(��!��e��Vn�V��h�;!Og��nQw5���������R��Y`�Ȏ
+�8� ���&�L�l3P����x��H(͏�����T|l���Qo�Υ@��6|��
+
+t0�5Ĝ��|{JB�LH���ў��t��Ӕ�ʛ�>z�q*����(y�v�y;
+�'~Ɵ��V8H��N9+5�+.{��=߃�q]�ٍ��l��A�𬌝��+�R+�N�\��_�RF�i#��
+4^0�*��(n+-h�~>K�a��U5��*�4Ćm���4�y60�q��Vz)u�	@l�C1�|/�}P@��(�5�O�X`[��z���Y������(���/wؘ��]+��֒=H�Ƙ?g�̭g��tnP�ی�ޤ�O��e�ك�F7�����9<ks�	���Dk��%��zk�
+j<�m=���X�6$֤���Hh�R��]L�������
+*��T�7��)��&��Z;�(M�=G�>e��$p�@1aM����.��:edA�zn��Y�t��gS��\����y+�2`.ћ0�RS�	�S�f8��������2�+,���Ί�F��n+Bg�|6���pg�&gI֏�/ճ��z����Ђ�]�}��$���A�����'̪絰F͸�����*����IK���PF�7�Ul"��C��7V�R�����C{"vh� endobj
-14 0 obj
-<<
-/Type/FontDescriptor
-/CapHeight 850
-/Ascent 850
-/Descent -200
-/FontBBox[-53 -251 1139 750]
-/FontName/SFIZFA+CMBX12
+24 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 67 0 R
+/FirstChar 12
+/LastChar 121
+/Widths 68 0 R
+/BaseFont /CPLBKL+CMR8
+/FontDescriptor 22 0 R
+>> endobj
+22 0 obj <<
+/Ascent 694
+/CapHeight 683
+/Descent -194
+/FontName /CPLBKL+CMR8
 /ItalicAngle 0
-/StemV 109
-/FontFile 13 0 R
+/StemV 76
+/XHeight 431
+/FontBBox [-36 -250 1070 750]
 /Flags 4
->>
+/CharSet (/fi/comma/period/E/P/T/a/b/c/d/e/f/g/h/i/k/l/m/n/o/p/r/s/t/u/v/w/y)
+/FontFile 23 0 R
+>> endobj
+68 0 obj
+[590 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 295 0 295 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 723 0 0 0 0 0 0 0 0 0 0 723 0 0 0 767 0 0 0 0 0 0 0 0 0 0 0 0 531 590 472 590 472 325 531 590 295 0 561 295 885 590 531 590 0 414 419 413 590 561 767 0 561 ]
 endobj
-13 0 obj
-<<
-/Filter[/FlateDecode]
-/Length1 1300
-/Length2 6348
-/Length3 533
-/Length 7162
+67 0 obj <<
+/Type /Encoding
+/Differences [ 0 /.notdef 12/fi 13/.notdef 44/comma 45/.notdef 46/period 47/.notdef 69/E 70/.notdef 80/P 81/.notdef 84/T 85/.notdef 97/a/b/c/d/e/f/g/h/i 106/.notdef 107/k/l/m/n/o/p 113/.notdef 114/r/s/t/u/v/w 120/.notdef 121/y 122/.notdef]
+>> endobj
+20 0 obj <<
+/Length1 786
+/Length2 1538
+/Length3 532
+/Length 2114      
+/Filter /FlateDecode
 >>
 stream
-x��eX�m�I��%��r:D�D	Arf����A:�CAI�nAB��޹��������ֹ����\�z���P�5L�@��e-����D���:�-nQD�a-�������-�-�HX�m����� Ɛ�1����1��?���1��?���I� Ɔ�����73d���JcF �& �`����Q�
-C���9�f{��y�D���XN,�[&8�����-����/��y�^��Ж�k95o�0G��`�|"S���2�5�j-L+rĽ��@s�M������f�L�z�+V"V� `��,����JPj�O"ԾN��!�G�~c�j��#'ͥ�Tk�}�ӌ���~
-���%�����e�yΔR������s��%�k€�?*'J��,�6��^��籊��2�x:�#���+�g�d���|�E����sE�c"���f�-%W���V'F��6�I����,7���7��pg�=���sׯ�KO�^u�`��$�b^�����-o�^��s�r~3�����A�����ÙeU�5[o`c~Q���`�!	�,u��_h��v��Z�*�~r~������L�l�a"�e�/U|��P�:2��[.P�%&��c��X3�+
-�G\X������z��������Rm.��X�,]�ge��Hg����-���YHM�ޜo�����5j��2yW${��P$F_Oz,������f������-�dZ���]-�0'E��{�C�޸��ڡ�▨t�j\𔍭y�W4ĝ���U���1��=o�w��:9��������[ګ1�*_y&g-s������D��1�����Ѓ��l >��
-KE��:3p���N�(���u���J���5v;^�A/=�&����!��Rw����7�[�M��*9��Bȴ�İbn���+�:]���}A�R�|�l�y�*r�sT�!�N�PP��yDK���/�>�������3Pp;�Y�=������oMj�0�"=�������'٦��G����f��f�XE.%��h�G���yI{�����9	���S?�c7g���y�0���7
-��BhOxO�Y�:�)E�*?J�U����Djo��H[Tۧ��٧_�������%��W,3R��ػeP:@������-e�����/���Yw���mJk[��N`�ŔR5��>�Vp'��tR���S�=�s�_\
-]�70ԕ>�w�����iXK�L�-�k6���7��IT�m��]����x��r�58�T���kC['{��;��ڨ��J�6v9L������!^F�JկyyQ�G1|&�[51�O��Oc�S͕���]i���6�D�i��WEh�%���&c�,��d �?�M�I{~��B�p����}"��4[a"���]�a&�*�"�H����-MY�-�(������?f��`�w�͇":u:�^M�c�[�it�������\'�U`�h���r�c
-�:��d;��@X�����<\����4.�a��養���5ޟ��F��T��}'�'��[�������C�:ʐ+����y�&Z�p�9���o��GuP<s9�_��U��-�emk'-�E��H�4	�׶��O`���z�>;S[�Iv���Ȋ
-�C��G *��i��3|ML�[Z4/�����,i�W�����ލ�d�ϧ,Z����e�5qrh�Hș-��-Ac[��$���!Z�Z����W���'s̞ܳ�8�s5���6������e�đŋG���L��E�q�ɦ��J��0{�-�b�����S��<i��C-7��˰(�Dd��A,9/S��ǰ�z�F̧�����!c<��$�ICT���z��T�u>��P�h��ͺ%<p@ӗ���,br��<N�>����3Gg��t-�����_R���k<_
--�?;#hnG�N��ȓ,��ylF���Z3���>�+��[��s�1d�+Q�K���Ms���T���<S'�K��5Ԕ�^>kO`��(�Y���>���[�{_�)S�UBN?�⎶y����*&H�/>��•��}���8����G�Ս�=�cZ}�$�e%X�P羃7�!��0m�lNb������Sݪ̲�g�k�FY���� t�*�|헂��iKy��k���P1������I���uN<_���Â�{���V�}��NB�V�_���f�T~޹�>Vh-H�]5{Ne芳)i��E
-�X:��T3�Ok�'N"��.z��7�����h��������ƫ9(f�E��tw�R��k��F+���	Ҷȁ���Z��I��V�T�{`9L���Ĩ;�Vަ����Q�V"b��匍�r����:G��E�=����d5D��ҍV��$�a�,�-�Ur�h��T+)�G����ذZ�����h�z��/��X��П����$�IiF[r�]�4��'��Q���i�u"������Ĝ*ݓ����@4�_�b�y�_�_�����A�J�FMh���������p�o�l�N@p�w�Z^8�b�(%����
-����.���ۂl ���o)&@�,��:�wN3����}
-��{q���R�����#
-
-Ň�=\��m�s+���7�#���I��=�ֻ�cu������Co��>����-|�(����*�X���^
-��QGS�{��Έ��'4�6y	�>���ގ�D��2Z�T�su�z�]pɶ��s��aӝ���ױ�چ�YȀGf��.��!B�dF�+�1�����4Z���B�M��@pt���KQ|���}jn
-;*-�MC5����P���I�[��z^���9i�;%܊0�d�0��Q��Q(Y���D-�t�B9�
-endstream
+x�Rk<T��TD�\ګl"13�1�ӦR�1�0ff
+kf0���]�~Ĩ�:�������\c�(ըD�����<��w}y���y�����0@g&�F��m+'��Y2S��̤! �HaBt.@H/���a�g��,�2�ҹ���6�L
+C�}��A
+����ѩd{(��/%*˙	R�$���(ߚ�ŶdI�$-��O�Bl"7����˲�����	
+��e��o�r��
+��� ����ͅa�#h�
+Q�+���SM�C�v����R�Bݟ$��o�-��S��������V��^���	s��J�_,*9�kU^������%��[>Ī���[����W��l�;�$������'��TD;�VL50���_���p���'�5��lh�9d+�L����m�U���o�E�*=�����,^�޾Uy�k�wfL��o��'8��g\1�/�|k��jϬ�������	2$�&�� endobj
-17 0 obj
-<<
-/Type/FontDescriptor
-/CapHeight 850
-/Ascent 850
-/Descent -200
-/FontBBox[-251 -250 1009 969]
-/FontName/XCHVXE+CMR10
+21 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 69 0 R
+/FirstChar 49
+/LastChar 52
+/Widths 70 0 R
+/BaseFont /RMDKMR+CMR6
+/FontDescriptor 19 0 R
+>> endobj
+19 0 obj <<
+/Ascent 694
+/CapHeight 683
+/Descent -194
+/FontName /RMDKMR+CMR6
 /ItalicAngle 0
-/StemV 69
-/FontFile 16 0 R
+/StemV 83
+/XHeight 431
+/FontBBox [-20 -250 1193 750]
 /Flags 4
->>
+/CharSet (/one/two/three/four)
+/FontFile 20 0 R
+>> endobj
+70 0 obj
+[611 611 611 611 ]
 endobj
-16 0 obj
-<<
-/Filter[/FlateDecode]
-/Length1 1867
-/Length2 13928
-/Length3 533
-/Length 14981
+69 0 obj <<
+/Type /Encoding
+/Differences [ 0 /.notdef 49/one/two/three/four 53/.notdef]
+>> endobj
+17 0 obj <<
+/Length1 786
+/Length2 1532
+/Length3 532
+/Length 2109      
+/Filter /FlateDecode
 >>
 stream
-x��eT�϶���N�qww
-��ww���ww��ι�����{?���rbEezac[C����=33@T�����I��\�t2��:�x-������W���[kk�������O���B\-�8�T�tb���ކ:x�|b���44R@�G܄w��V/1�̌l3.���^�N�8J�E���Zd�}PH��;;J�٬��j֍펎`�1�?#ŧق��mr�k�D�(��3�ʭ#9���ŷ-��r�a`���*������>���֬	ZcJX)�(�.��o��pO��-f��=|ݷ�P����RyL�)gx�=�w*z�!xN�,g���쒁-�1Q� U���V�Kb�LĂ��d��L��0�j��92"�iQ��锡�nEx������`/�H�_טEra�N7�Ռ��D�u��e~n�.<�s��+���B��3���=�"C�����"��X��|Bj�(D�mZ_�C�l�0��s���ȉ(߂O|Y��1����m2�O��*)�������N�`����7�Xe�v��:w5W�Q�Ϧ
-�����n����B��a@I���{���]�t-Vf�(B>[��d�s�Y������<�����,X�����xgXQ���S��"#�D�UE'��kg�ET#�
-�ș���������,���G+z���Z��̾y�uv�?�1'l��
-Ϗ�����@�k�T�hu堘/7AZ#m+���>A{\߹�D\<�0���Щ1��V�-��邆9r����.���	Kǎ�Б��$�"p��������S�-py4��-I����A�����C9�d�h���4	e�"h�J
-�g�]�y���� |�F��2�x�ۖ�ʳ�U����W����������d��~ʶ(���0����	,�U%t�,,�*�{]N
-X���5�/���XE����%�`bҟd���g�u‰=�����2��x�75��D�� ��v�ߣ�d���0�F�YG�"�6	OHS�<��6���1�2���j=������
-]^��d���ͯ�Y��s;w�{u��ʰY��DV���������ǧ���h���q�ǟ9:������
-��b����)�ݵ���r�vs���aL�)�z;�^[1�����8<�Y��*��uݵ%ɓ!tBA4X���p9������y�^���G����
-xn���Y����:X NPkYy����?e��k�\����+Vnҋsg�#��x��Zv���Et(>����^n":��(rޜ���4����+��8�a�˃}�B��k�Qݾ�~��6i�H@/��͸Q
-�������rG����E�܇g�/��)�%��>J���(%�QG�xbx�z���|�������P�i���i������^C�|z�8�����IհL�D�l(���k�z���nY��2�w`����v����Saԃ>�d����8?��[#�����K
-1�H���ݰ&�`������݄&�J������,G8k�9��׆Xi�B����Z�D���u�nIa�];d�h��@6�6>R���Q�'�V���ej��{��1<~��=�g�-涾�f�z��9�4C�;:��կ���.ȗ9m����K0��Op+H����1U���*X+�s�v������V���!9���~mV���U
-w�dհ�X*�����@�\l�'В`��K��|���
-�Ts8�K��o*&������:-���Pw�a-����bV�e3b�!�(\[,UQpBR��h�PZ�&s.=�����Ağx�F:�א��d�����c��AwO^��K�PE��ȱ�)>��Z総��>���wAo�oX(��+���1�t����J\$����f#v��f%����2��V��3�C�9a܎���.�O`0L��ե�u������U�Z���qn%Oҍ��� /����:o�_�5���Ő�?���7�)�<�ܠ���79�[����	ym���_!6-$I�J[�erX��	p�����	[
-��(/�8�we�u��<fO͸�	V��������-ȫ�tA��I?Af (k�|���N͏F�G��"���/������o��.8`2Ƈ��7S(oJ!K˷*�sN(N�H.��Z�y_M-F�?��&��;{�u
-�Q��ëiӂ��N>��5֊rNl.a�������6�t��@т�3;�*��;��,4���������K�7�n�{�nJ(�����.�����5X%��\�����������67�`t5��.�H�Cm����$x��{IJ�l5����JΫLF�?/.E�d�ո��N{.��9?�ㆃ@������=�m��v��k�3���C������� *C�VnIff�a����4a���N�l��/�j��֠���T��Q\�����ܿC��N�+�(hzQ�5nG�G���3)��������)���cD����ݩӎ|��F&+f���|s�IL�6CK�8
-c�F���ȩmo'G]$��Q�c����6��������k�Kx����S���\â4�\����b��	\�7�`��V����Ozo?�����Kr�N����?�l�zU+��Z}��d�V��Kjy
-�z:RL��v&7a��G3�{0ٔ½����a��]hþ�v��>3�U�q-��k-�&��;���\G3yfݴ�sE�o��)��TU�z���+.GFg��g	IC[h~ F��T�Y�{��6@�N�?�@�X3ܘ�����d��[�`5��'����a��KS4�X�):����y�n�K�u��4��B_�Y��Ah���}���!92�7�ġ�cHY�~�ʞ���i��3��g�Ϫ���O��2H�� ��e�B}�@��-2�j�m�@e����(��8>ۯ��}���6��8:�wH~�f#���V5���U��UZ7�A74�
-��&g5b��U1�*�obL4*8��������y[��f��̠O�R�#�$��|ɭN�zBg>6Uz�~OI����k��Ƕ������6�4�*��m�I�]�>#�)����j!��o����
-㤭��t���X��o�N�]���~iT�d�rh���nӗ����-�-��!e��"��wZ�"z@@��D��Wk(��f�S�+�k^�%QS�MDž8Wݎ/"��~ɦ��Z�FR��̟�L���2���2����js��PΆPs��$)hȿ�GiK�%`m�H��Pjj�yg2Gr]+�BqT�ys�����������VF�|��I��m��$,䎘?����t'�d���v��{�͕m�ttW��Q(�x���B}]3�D��-yOJ����-�,%k���w<{���@��1@M��o���.PL����1VПiԧ��YӁ�b�ڡ3}pT�<*�S)����F��|�n'����գ�B�F���Ym��4_����E#ZJr��X[p�$p�#`���L��JdB��iS�~�̮%{}�:	�:�����D�=�6����� �:�� ����!�H�8�>��Z&:�Sf>$'�5�![H*���`���R�q��?d#�'���L�����2�?�-DH�  �b?�v'��}㭾8ؐ������wHM���0��)Ql�����$�����,>�����q.������2��������M��#��(c��ѦI��(���W��F������Zv�i�~"���8�����Z�{G	�F��4<h!u��k���t�?P�5����5�&,�����Js����s�,�|>�z��s"�Kl���f��ԿZ���T%��No�<����AA���DX�B���x��-��]��u![�}Ի��W;���������x�'m��
-��pN8,T��h�����t���d��o���M�a�d�{u[����[��RBII��w�	S��u���pqPq%��-J}�Nii|U1��z#�+�鼤�v�'s+l������[�-n�_��U)um�R�O��a�?�c\��G�j�(�U�rN�`��V����K��o$k�%ण��J�'�g�L�Qe!��Ov���5Qwrƾ�Շ�5���*.�JO۹ߒӇ$�3�"TӰz ɨ�W%.�/�L��7��o��@���q����	!��wPu��X�-Xp�2�Dž��8�K�r5�ܽ�~lp�eU.�d����L7R=!�0���mtL WZ�=���@2LLQ�F�縩���W]:E
-�(�Tx�m돟�<ջ�e�hc]?�u���\������YM,��Yi���C�">������p�+^�&�9������"���B����Nߩfo������C��D
-��5��[���똹D�=��KB��(��|�*�گ�W�<�Qm���+�:
-���0�ofz�#ʞ��"ǑT�j��_(L����RR����4X3�W/�v�R�;6�3�����A���J@��I�ǪП��j�X��fz��9���������x����<��BF��C�x43�H.��A-����bY�$�߰��c}4N���z5�"�~<�l?7�kP$߷Y����'�a���ք��Ҏ��d0��A������Ȍ���<���լ�p�-�
-��	Y؁y���;D~��x������r䣵�%��o�z�����dJ�}��i��H�$�tN�*[���[�D������_��z��t��~��#���@1)a��=�������F7Ǎce2��-����-�����L��=FԿ���8���c�X*d���Ĭe����J������H�����0�-�5v!����VH ��9�(�?�(C�`����&���5�U��(���1�O����:�U��J�u��Y��7�(u�A���j�T�������eφ�'=S<�;�'/��0�����;B�F�`Qw8��lmF�]��S�/�e����f�j�A� �����F�q�S
-��~��i�ô�L'*�{��]rvB�R.�b���+���j��B�R��0�%p���f�� a��=�v�E�����2?�������l��Q����!ߛ|=T�KAQr��o� �M?�}��aت�L����������g��9���o7��[�8�@�@H��/;����-���7A_O��vx�� ��ʁ�5͎���OR �8o��^hȀ�Cw���(ќ��
-�uF�����/.�Y������ZK���V@C�ܞ��L�Y���l����!ڒ������oh!���c2����i��l�~)�-J�����Z%礖�p
-�?�
-�л[^F��^�<�endstream
+x�R{<������hsr{]&��K��QF�uM�.c�3���DjS"���agʢ�KIjZ�R4���s��������!���P(H��k�
+���06h��Rx����+�Q Oh�L������f�+'�
+S_���$��O]
+�����8|�< �I���*W6�1؊q�.�"�)�p@`�i�+�(6���t�[zL[{+�|5���Lj�������ii��+y���:ٯ��|��0M����W5of����OsV��ET:�ֹ��k�j��e��%�1�����8�l[i�@6;�ϧO�>�Yl��8����Cn����(��Dzt��o<`�S�����w����w�fkE6z��$����O?Y���G>+<����q���5���u��`Wן\�����#�}���;s�����o��*~��G���+����/,>v^���9Pk��.^�l^�t`c�qp�·>�m�#�Z+����^-������T&H��{�\�ndstream
 endobj
-20 0 obj
-<<
-/Type/FontDescriptor
-/CapHeight 850
-/Ascent 850
-/Descent -200
-/FontBBox[-27 -250 1122 750]
-/FontName/GCOOBE+CMR7
+18 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 71 0 R
+/FirstChar 49
+/LastChar 52
+/Widths 72 0 R
+/BaseFont /WRFXWO+CMR7
+/FontDescriptor 16 0 R
+>> endobj
+16 0 obj <<
+/Ascent 694
+/CapHeight 683
+/Descent -194
+/FontName /WRFXWO+CMR7
 /ItalicAngle 0
 /StemV 79
-/FontFile 19 0 R
+/XHeight 431
+/FontBBox [-27 -250 1122 750]
 /Flags 4
->>
+/CharSet (/one/two/three/four)
+/FontFile 17 0 R
+>> endobj
+72 0 obj
+[569 569 569 569 ]
 endobj
-19 0 obj
-<<
-/Filter[/FlateDecode]
-/Length1 845
-/Length2 2042
-/Length3 533
-/Length 2661
+71 0 obj <<
+/Type /Encoding
+/Differences [ 0 /.notdef 49/one/two/three/four 53/.notdef]
+>> endobj
+14 0 obj <<
+/Length1 1842
+/Length2 13515
+/Length3 532
+/Length 14535     
+/Filter /FlateDecode
 >>
 stream
-x��y<�ǕD�Jv�~YJd6Ƙ!ːB4���&�hf,C��
-�$��-�d�5��J��Y��tF�Ϲ����~��|����d�hà���rpF(��m��l
-�nMd�X-�@�J����-[F�������RBO8G����g�d
-]�-�!�?5B��-���$HV�"e��������js��(=y4.M��v��
-�u��ǟ�0������3�G��WI׷힧`[�8��T��%��g�^*� ��o������!���\��]:pj�FK��O���x5��S����E��MZ�v��d�Dט�[+Ռ?\���M�k�Sb��#�����4#졜m��T�ơ��kVF��)&�I�1���F�{l��u�%}'s~h�KE"�w��셌��N&p����	i([������6��(���-9��)8���M˥�(�h�Z��(5�֕�ϴI!إ�$�KT5x��~�p��4hO�q�Wn�}E7gѺt;vh��:��<��B��׊��!Z���!/Z��\d;*eom��\p����5k&Jn����_�S�~vM�tD-E�����-���#O�߽�&׹�9���L*c�M�r��P|qd�!����5�aGo��b��@�����2���kf��T�V�ك�΂·,L�|��]��ɐĊ�
-?ӊ����ȿ?F�}��Ҋ�W�‚���A�Y:-y��J�����r����������śp����Nd;�����
-i���[f���Wm�8y��q����`���f��,��SO�򚓸���|tF�D�J6h�?�t��z�i�f*�ۣy�i>����-�i�l�&����!6'[߇k_g-u��Ƃ�?���$�}��_c�z�-}���%���������g�p����A���;���&垵�9��v�_N��ڦ=W0jV̨n&ܰݾ��!	Y�
-7J�@ĬBZ���F�',��*���w���.Ĝ�nS�m�7�OA��r_d�Y�xr�}�)���]k��i�&լ�����;�����rU0QK��9��W4E�j0H��uT���Ϝ��7p�G��k��W����%�[z�-�ٯ�)�l��#¡�i�$E\9�t��I}q�
-�7=#0�}��k�PG�؉�stV���Ҽƒ⺒h��ȯ�����'�ػ�����W�f^��~��Wsbz����Rp����>��a?�5�ySo�����T��u5��y�����:�������E�ފs{�?]�~���᫙�Y���b�f�����T�@��_�؝��{�����!��ϨQL���+�Ђ�6_�
-(� �/8��Z������HT��3hDf-endstream
+x��eT]Ͷh�kp����=��{�.�xpwo�r������9F�Q5k�*(�+���l�i�+��t��ۙ���+i�0�#��<�d�z�	��̌�-�1���+����x�Ћ�{B�^=3�REz������]�4�]?��gSRm6	3i���҂l���h�N|��!j���d���xx�0�=���L�8V)э�O��}^b�Yqsi�Sa�!椑��q������1l�g����Jwu���嫦썝��r}��DzQ�]�������r|r����iGu�U̦���M�1g���Bj�_����z�ҷ���>~%����j�� �Am5Ύ'�Z�Ɍ�B��
+����^ȭ���~����ǽ��;I$��9�/�%L%}Q�ZB���PY6��������������n�����Z�c�ܠ�k��ؿ-��nT��cn���H�==����j�K�����F��o�`���
+Ü����@�#��Z�CP.E�A�(��y�"Œ��=�]vW>:D��/��˻�j�`G�[��p����O��e�z2رt�6�}\� ��kW�5����f@��m�Z���"���9#$U��#�}��:�.Q�JI��3�.���Kl<X��V�.�5���8Ü�L7�w�p����"���6�����/�+�7WlV(&ɐ�����.�[E�7Z��>�-�rmk,�h�堦{���T���1{��In�d�O&-i�A=�W��.���������B�^x���{X$��rqö���Q�<�����
+�����:uW��1�[���{�C`V
+��i���:���b�߫�]���?G|q��8cJ�{a|�v�,F2�ޔ$��lPJ������Ub�Q��ky1��F;��ja���&|�d�o��gg��q��1���|�v�����Ų�EG�Qߟ���Јe�>�Xu(���N�nH�O��0����sY�9��	z5����'J��!e��������ͺT-������
+u� w������0xBv��& 
+qʜ����ע&XT�xe2�ąLD𹌯�4|C����e�$��zඋ@�YO7
+W1;�3Z��4 �t	�C[�~$��|l�d�Y4:X����F�;t����������	5�G��$`�������������+m!��[�4�1mӤ����i���J��:��yxс������vM�$��^���.e67c�e��+7d~;�+���"�x�<�E�E)�����2�sK�l����c,1)���u����r��
+6��zTv$�+��ɦ%���#ض��!������ou)�9����
+�#�,CNʤ.jZN!7X����qN���df_�JO�����[��/�*��ou���f�Z��K�G��v�;��-;N�DX����޲~`S���*C/���E$�����I}�,rP8r�Bm�sdL�����i����{��V+�6,�zєL�)��˒�|L�X�-�S<#�n2re����Y�B@g���XW��b%F-��k(�R��E�������T��k7�Kd���k��5�~�2�cȆ��/��z�c��8r�>!���zz�Q~p,��X3�fߺ�
+K�R��)�u����~�)��ɽ����鉙�ڭ�̞+N�|�<����5�,Ҹj�y�0�&�Ai�.�� P��̢@�_�~�?�\ӛRq���w�Z�+w��H�8y��Џe)�kѩ��4���u�·s���L���M��=T�T�U���~C�ݓBD��y(�"~�ϒ�����#W���8���q%tq��Љ�d��+��9�uQ+{\t�d��Dqšpb�lf����"&��r&!���Ķ�����V��x؆i"�i$�v�B`��tW�0���"-)�,5O��2(l���������;�K�E�`�
+�z=�ܡT1&�뭳�F��[v`ֱ��׺<
+�@u�k�$.e�V�a���ʨ���r,�\��0��GoW��- <Ƌ&���� E9o���L&/xt�b�t�v@�������V�nNC)?��ʹ��+=|?빢{ʅ���1||mp,H��@-��ADD�����Z��_E;���;��{y\�Z�'����y���0\\LM�l+���L���:�[�����И)�l����B�ޘ"����̙#��q��:ל`)H<��WX���i���k{���jV��j>]��O
+�p!��W�����ܜ���A%'	L���GǕ�'���Jܡ�z���W��֥s%װ)l����2��+8��
+O���z�p/����*�X`̑kp�	"u�w�G.(~�f���9`@C+f�1U���_*ڊx�++c�Y`_Z	�c9B��T>	���!�q�}�-�1Qa0����#�<�_dI�+�x�����7��ĨyB���:n0i�S �Z^傥�u��;5øb�S�A�7	P4���U����X::�8�ܘ�*� '��0�>�7i)/
+���D�@z�X�M��U���������-S�ݑ��^�b���Lbzs��}-M��'u���ϊO�r9�{U��s�%4>���V�2�&�]]Q?��d�����82��RE/݅X�zY����C��ŷ�C������3y�ΒK��+�i`6T�NL���۴D������I*,!�~�Ҩ4����"Œ�B;郯��,d��
+y)V�����w��2[ʢ�'^�a�+��ƽ;K#Hy�����L�D��~��U�#��/��N�J[sa*��Md�fX�����0�����S��Ld���ۡ�)�2�J)[I|9�u쎤L�7�&z�VAJX_���vF3@⻃�m�����⛙����Dt�� Cy����CN�WB�b�==�G�T	�FDM��@chyuU/�W���2���m/
+sb�����kp
+D��=��vV���=����:b8`:Z���9����uHKbU5:#�":%]t�������+;����>"������
+�T2��!᠌N��v3pI�͎t���p��Z}
+dV����*�+L����.��<�%����m1��*;h��D�F�#�����H �U��n�ﱤv���sC(��אG��
++�\�Ƃo�����m�/n�^��Fu��O��cU����I4����
+���+�ȡ2vꀲ�3��~��}�:��x�X,���﵄A)p1D��īTSbH���Ut����������	��;�{#��ޫHO+�Έi��o�n�)UY"Q2l�tq��ˮW�@��*Sz��G������4<m����dέj<0)���~��,����������Jn�����10���GQzσ�����BJ�l����I�ל��4���^�b�p�??�P	8�2O���@?9�&F����*qh(�j
+���G����{��|�"rwM�I��$��0�t��B�Ua��C��qV�45���#���-�)�>��دl*Y��h6�.������J�[r��W���
+�,ej|�m�ۄ{�=5�����wQ���w��n��W��
+��:��KA��Aw��d�۾�r�_��c��Ң"�M�p[
+��7_�����\����֫����\ȥ�ʀI�{��W8Tv��7:������[�����-������[���j���� �d��+V��I/�J(�c~����0���q��r����<���(De$k8���2M�z����s������W
+���	�Ok��+�Z��_�����X�w��c(�*8� K��t�����V̕�j���1E<��k�\LP�l'�:BA�D����5�[MG��o�f�����u�7�r."z��e�t�Qrk�ژ܂U�D��K=��+���ܣt��X�"�(���?Ci/Y��Ú�KXM�����*�>KF.�P�[7�RB�x�p
+�s�Si4qG��Y;7�M#(x��w��M����@s����%wN�i��ϖ����נ��TQp�K��������x�na�)wĪ��-���0�y��tPǤI�������΢��E!������0�ѝAd��;bU��`S��~���bxi��sG;�	�o� 2w\f���o?��|)��T�ՠ~7k�W��5[4�'�[?��|9����nj{��	{�b��m�v�<�۠���ռ-���M���ww
+UfE����Uv������Y�	����O�hِ�Gt-����,��^,��p��kݪ���'�J�=��<�|t�+y\W��FOm��(��-D��s�}�&}C�3����9l؆�.��;7O�.����̳��+��D�=-o��B��t�?��'����a��51��Y
+�����b���8a��&Ֆ��Ͱ�0E��Tּ�L|<F
++�1����|�4ӏ�jq���+8}�R���v�d_ɚ�{��[�?":ˁ�Ar8����
+�|�C�-1$ׁ#.��o�����w�>�?ٵg�A�%����#�U�C*>��������|�P**_n5���mB�x�ר8<J~
+��
+6Y���ܾ܎_�	1\�a�:<]��������p���5����b���(%
+֐w�DGo���r@]/����Cj�W��Hy�����G���;)�hI7�haxu�i�S�l\�_��XL��	�,A���NH]�ݷ�����}m��j���b��a������_����@sc��L�9{���r�ᦩp	o	�mVT��b��Q�>����a��}h�-����F��������K_���a�t�S�;���bޙO�y��N�N��Q`��T�����ݷ;񅩪C�V�l�{�������sa�F��"����v$���39�~@�l��/���ǽ�����D9���q���eZ��+���y�dc3�h����`)	Ԩ���g���Tߓ|y��:,�YfX�q,ز��1�O�-*��λ�S��,z�(��[�'��u�m�jK�R)��U0�Ы���O�N�1���/J��
+.��)��]��yL��x������f�n6���ď����Iۏ�Ču�A�����"���a��Q/+��fY���CZ)���e"_�]Qx�@�U�
+Y�S�rۣ���$U��sQ���p0�W��3�ʾC�Eɾ� {�W��w"�}�G�t����1�v���M��g1�}i�������t�C��r2_n}��S��,YM���i(�&���;�]�;����C�����tIO.Wjx�����:e�*�X�;]�{���ڕ��7LM�>,Q�M��Av�����8#?��)���7N�F��g��a:Y�e��K�bG��'���F8bJ(C���n��������L��W�<��S���)R�:�� #�p�����W$�L�`*��y�[L�����I#<gC��wb�g�ŨT�>��9EQ�>\K�O���T����H��S�BL��6zͷ�#s�KLЦ|��B�`Ժ�����$
+"2�S��`���z=2�S����2�O����+��*�ڧ/m�gD�C����z�z'u�L�{�Ҝ��=P��vF��TK*=����{�����wЯ����;��+���@���=�Q����u\l1��=h)y@�`��¬���).jgT-Uy>/O�ˠ��PX����~m/�+f�HQc��헝&h�`B�i��U����aO��/��5���/e�c'�tG1P���N,/*�ҙR`7v��яlzG�����M��k�J�$C}�>�"F��\��cX�Kj��-�e�zu�ئG��.�p�>|=jZ�:��<ʸx���,��L[���)�$ko�g<��ryW��k��vm��ЗІ���땆�TYS�0���mm����T���V@�F�`�M!����{ t+q��5e����X��yAA�}�Е7�aQHI����_[&����FTTϳ3C��k�e��Y��$�4�x�%��h釨��n�jK��d�����$[�%�}_.P������	�?��h�gc��ndobj
-23 0 obj
-<<
-/Type/FontDescriptor
-/CapHeight 850
-/Ascent 850
-/Descent -200
-/FontBBox[-20 -250 1193 750]
-/FontName/DMIVYN+CMR6
+15 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 73 0 R
+/FirstChar 11
+/LastChar 122
+/Widths 74 0 R
+/BaseFont /EWBXHF+CMR10
+/FontDescriptor 13 0 R
+>> endobj
+13 0 obj <<
+/Ascent 694
+/CapHeight 683
+/Descent -194
+/FontName /EWBXHF+CMR10
 /ItalicAngle 0
-/StemV 83
-/FontFile 22 0 R
+/StemV 69
+/XHeight 431
+/FontBBox [-251 -250 1009 969]
 /Flags 4
->>
+/CharSet (/ff/fi/ffi/quotedblright/quoteright/parenleft/parenright/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/question/A/B/C/D/E/F/G/H/I/J/K/N/O/P/R/S/T/U/W/Y/quotedblleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z)
+/FontFile 14 0 R
+>> endobj
+74 0 obj
+[583 556 0 833 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 500 0 0 0 0 278 389 389 0 0 278 333 278 500 500 500 500 500 500 500 500 500 500 500 278 0 0 0 0 472 0 750 708 722 764 681 653 785 750 361 514 778 0 0 750 778 681 0 736 556 722 750 0 1028 0 750 0 0 500 0 0 0 0 500 556 444 556 444 306 500 556 278 306 528 278 833 556 500 556 528 392 394 389 556 528 722 528 528 444 ]
 endobj
-22 0 obj
-<<
-/Filter[/FlateDecode]
-/Length1 845
-/Length2 2056
-/Length3 533
-/Length 2671
+73 0 obj <<
+/Type /Encoding
+/Differences [ 0 /.notdef 11/ff/fi 13/.notdef 14/ffi 15/.notdef 34/quotedblright 35/.notdef 39/quoteright/parenleft/parenright 42/.notdef 44/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon 59/.notdef 63/question 64/.notdef 65/A/B/C/D/E/F/G/H/I/J/K 76/.notdef 78/N/O/P 81/.notdef 82/R/S/T/U 86/.notdef 87/W 88/.notdef 89/Y 90/.notdef 92/quotedblleft 93/.notdef 97/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z 123/.notdef]
+>> endobj
+11 0 obj <<
+/Length1 1292
+/Length2 6411
+/Length3 532
+/Length 7207      
+/Filter /FlateDecode
 >>
 stream
-x��{8T�5%9DB�[�w�w��3��5c�1C(��%�P��%j#��-�FIR��[.g����;����{�]4M�_Њ���`n��+��F���)]���x���^��P$��-�i����U�Q��9��unj;�LO�A��w�6"º�b%��Ȗ��:l}N3@�G�<GV%�
-���f��S���lS}Ԉ�:�����W�[������|��r��n"����ɞjY>���T����^��:rL��pj���(�ʇ§q��U�c���{D"�) �B�C�5��*��;�(X[���\�Rw�$
-�Us������OV��:��[	J��<-<,w5M\iI*�kmטh�h@M<���c���ZN��C#�O�n��d��I>�N4n��-U?�����}�v�����%z����D��<-�;�endstream
+x��e\�]�DJRz$��;e�``����CJT:%�Q@BJD�AJ$�iA��[��<����w�����nh"�E9�QHo!�0H���l	��EH��U��7�T{� @� *+�����k
+�5������+�a�`X'�7L�B���8"�P��4@�����j�����8D	錀D��{��aPC�7��x��Ð���m���jƆ��3Ͽ
+���i��e���A��4�`#","�b�����#�BB++J��+�o�c4jKQ�Zߖ��ݨM��iZ(nsq��e*���4�S���d�s�xw(kxs��<�����ZK��V��Ðkr=VHk�`����Ki���9���	n�jO��O�����P� Ɉ���Z)j��_����P�D;��D�m��,-~9�tOݯQ{wD��'�L�s	�a!;��0q&���4_��b�k\�¥���S��P��5s����P�5��kK�����ƛ�����[�}����/�.��;g����G"Êy^X|R�^�oڡ���������X�/@h(�|f���%�	{�i62������t���&3��ǃ5�#��S�-�9�+A�R��� ۄ��6����H�8d���*
+���0������+m��;z�g�7i;��3�M���+��&I����������΅�|J�"��d4lr��u�Zg���!�B2�@�Xk����GCNl�u-^���~�p�*uD~^EQY��>����_��]���C��3y����|a�M�v!w|hm	����=tJ����Wy����rSO�����$�=ʾ+����Y�`@�<�rF�?�+4����TR{�>Z�s&P�f�='@�O0d����:�uL~��$��q��CB��y��\�4�W��㾱��Ì���%0�)��t���uQ&Ơ���u#+S�Kj��w��\��1'�+���s�tܵME,�������s�]���m�����457١MX����t�J�6�Q/J�OtmvR*_7�T<���������Gφ_5/+
+5�L&��C���/���=���&�ڀ���+�:3lK\�q�×	�k����(�"T�R���(�r�d�������V��o�5�2�v�Zb���
+~���B���?�yH�'��Ê(
+np�	I�Oj��+��ù�:=�x��E��#gsK#I8ܥ#�v4ny<��lx��<����.�s<Z���G~����/*nG������_
+�kvn���?�s�x@H�>�}��e
+�+B�B�s@��o�o>���q�75�n
+z��j>?��w�1��R���q)�Ӻ8��lf��]ǼG:�_�2��֏�o�S���Jf^T��ۨ����ó���wؽr��EԼhMC��8-���*Bˎ~�U���#DT�2����&��N�i̭f,��B�wl"O�����,��b
+B��z����t*L��wFcŇΟy�������(Uk)+	nǘY�1���� �6�]���"�(�IuՒOl}dGQ0�X;���_��9��%��ʜ�H����$���=�����W�����q:����d��esA
+vGT�J{�������>P�_}����BEWq0R���̸���{�g3y��t�^v��8�^h�	�{����gy�b57�N����HC'��#q�g�������W��lX��ieݵ^4���+��KM����>���Sj��Z:Fs��i���y.�M�ҤAv�����]����Z9�8��5 �81Q%��L�Q���O��:r�����"Q�4*1%��Y.�lv�E����GG8��'(~�<����0�*���L�3�����H�!�G��G�U4s����X�`�4U��z=�|�*��+��>S*a���h����8r�H�c8���� QK����ո�g�}|��v���T\�Ut�͒�h����o7��R�Iy`�>���+���3a��u
+!���r����l��k6O~`�?����U���տ�X���pJF��n����<�b�������>��.���6߷���{�"&�����p����sK�E,ǎw��[ބ��e��c�C�.�u�B�
+���xӄ����e�8RF�\Htt^=��4,llO��Ys��*���1�;aR����jsu2Q��K�
+|寭!�9vv���p�����&G�76G��������1���/I��E�¬�
+y6E�bp�1?�Ϛ���nGͧ�+��Os��cF�g�C�Z��S��C�@�1��gb�r�4S��,��)5��h����q���kא]*�n�Y�l�&a�=��K�͓�Dc�;�c�E���G��H<M`����[8N{*5�*��oI7�
+�N=A��6Yٱ5�|�C�d
+l�ѐ1��^���t}'��Q�܋�w�U�_"f��rOey�������8=q!'mEa����:���US˓��d�Y8KH�E���aH�G����ggc}�WV����#J#Zo���Ty{8gZR~��+I�؝71I�^����%ח�����%���8�2�q�
+�+�����Y1��O����&��b`���t��|�ƕ>15����eh���i旘���_��b�(��o�e��sb9x�h������Y�C��G��s��|�]m������J��Xhfx�-7T�K2���"���������I��Ӽ�n��!��G_|��ԉ��\�Y���#'[E����y���1̦K!� �MYZ���5�7���T޶��q�O�hk/t���i����"�������+�Z�⬖"�xW�S$O������#��o*�th����7j<~��v&bҳO�#��>U�\`��~V��I_ѡ8�'r��q.�5`��+�
++��P�2�:���c��ڦ��o�t?�H�S���N������J��
+ZZ8�
+��#�T�1|z�ɸplwg6��$�+,]������F��/��K��9'@���n;C�iQ��w�d���R��\#�H"k���Q�=�ǘ���H9����q	m��F���`N�Jl*sVb���ӌ��sL�c�m"��,��4ڌ���g��]%1S�3��k��(̨��Ga�o �M�����se�*�6�p���uC�
+(��rɓ0����3��|u�`�w҈4�8e3�'H�$�\���N�$E�r�����F[E/��pڵ�,u�n"�jtj7�}_ܜ�H���l�?T��D���Q��T���/�2�L2v:X/��֗
+���>	���+X߼�+βo3)͙��}�[��v#�q�(c�Q�����l�Z�>\cA
+n-�30��;ۚ“
+]�_7�������P���f>�:�ʯ���Эf�lD_����~}T�M}'@y������U#��n�+�������.��87�sk0-�[l�]�����E���+a�%ŧu8�m�2�+��}���%�2���5roAZ.>��46��S&O��Z��޻!��
+��c�d2ŷĮ�K}�i�������Y�O���4&Q��+O�K|3�5[z�L�_	�w�uC;����	��M	[{���L׆���l�<�?P�)p��t;v^�	W����'
+@00�����/
+�endstream
 endobj
-26 0 obj
-<<
-/Type/FontDescriptor
-/CapHeight 850
-/Ascent 850
-/Descent -200
-/FontBBox[-36 -250 1070 750]
-/FontName/MAMUVX+CMR8
+12 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 75 0 R
+/FirstChar 45
+/LastChar 120
+/Widths 76 0 R
+/BaseFont /PERPTG+CMBX12
+/FontDescriptor 10 0 R
+>> endobj
+10 0 obj <<
+/Ascent 694
+/CapHeight 686
+/Descent -194
+/FontName /PERPTG+CMBX12
 /ItalicAngle 0
-/StemV 76
-/FontFile 25 0 R
+/StemV 109
+/XHeight 444
+/FontBBox [-53 -251 1139 750]
 /Flags 4
->>
+/CharSet (/hyphen/one/two/three/four/five/six/seven/eight/colon/A/E/I/K/T/W/a/b/c/d/e/g/h/i/k/l/m/n/o/p/r/s/t/u/v/w/x)
+/FontFile 11 0 R
+>> endobj
+76 0 obj
+[375 0 0 0 562 562 562 562 562 562 562 562 0 312 0 0 0 0 0 0 850 0 0 0 738 0 0 0 419 0 881 0 0 0 0 0 0 0 0 782 0 0 1162 0 0 0 0 0 0 0 0 0 547 625 500 625 513 0 562 625 312 0 594 312 937 625 562 625 0 459 444 437 625 594 812 594 ]
 endobj
-25 0 obj
-<<
-/Filter[/FlateDecode]
-/Length1 1289
-/Length2 6434
-/Length3 533
-/Length 7245
+75 0 obj <<
+/Type /Encoding
+/Differences [ 0 /.notdef 45/hyphen 46/.notdef 49/one/two/three/four/five/six/seven/eight 57/.notdef 58/colon 59/.notdef 65/A 66/.notdef 69/E 70/.notdef 73/I 74/.notdef 75/K 76/.notdef 84/T 85/.notdef 87/W 88/.notdef 97/a/b/c/d/e 102/.notdef 103/g/h/i 106/.notdef 107/k/l/m/n/o/p 113/.notdef 114/r/s/t/u/v/w/x 121/.notdef]
+>> endobj
+8 0 obj <<
+/Length1 1065
+/Length2 4472
+/Length3 532
+/Length 5179      
+/Filter /FlateDecode
 >>
 stream
-x��e\T�iA�k��a�.������RR���Q��	QZARD@)��w|������̵���9Xu��ew7PP@P
--�	98 H�pwS��`R-}-�7��S����-\�@���Dk��?����_�?}�?���5|�@���B���(����B�������C7��`0X\�������!0��Nzg������)��\�y��0gݓ���g������߭�����JU���h6��ۭ��Y�8�/Dyt�ҵ\Ύu/���4nFou`H�*�Y����؛Q��Q�>�6<��mRu4i(m.|-��^Z���'�Tz@�GY�yd3���	��	�!�'"%��ZYmן��Q
-"�h(�+�ܱx�n���d�l|?��h���m��\�+ͦ����/�
-���k�3P򙶧�7�k[�/����5\�V��y�����z�G�������`6��	
-	�V#z���q��+�D8)2���#P��9��U������_�l�bM���!�l�0Q��# oKQ�HC��+�_=���m�ұ���D����X�Z`Ã-�_(/]�Xؘ1�c䯢Ǽ[<ZV��QrJaN��d�\J�����˙�mqf�`���3S~�+���ΆRf8'C����J��+�X-�P�!�)�R:c,��ЮDw!�m��P�����p
-�q�/�\���m��I��PG�����8gx}gQ�1��C�j���A��yĵ����*�����6�X�-&�fr+X �|uV%���Ⴢ��9˭2�p�� ����)�%�u!-#pc��Y�Zj�R&�����,/D�{.�p[��7`
-sH�����֡�;��@o(����$�0���/;G�oZx�K�a�VUn��)e�s���J"ג��|M�u��L�����Xk�i>�?~��˹T�0
-��er�B�g�^��ў��
-e-�Kn�N�VC/���*�B�9ڵ,u���g��iq!��KD��]�ͥ��I��l��R^&�f�"�g��2�>z(J��s������1�p��J2��
-�J�fEx-o�A?7�R�Q1#1&Ax��\
-/��(ae�H_H���]�ڍ#N�ŷ&�����ƣ��<��48R�{��$��K�|lu���!c(�a�������j�Y9�wV\�U_�a��+�ta.4�[N�Z�ƷI�ȰvFvtΝ��EG�"��
-�պJ��g�������o�B�QzU%���<
-�w�'�gsI��]x;��<�#O������/��o�H����/��t�������>����U�/,-������a艰�d6�򃼺>����B�)S;��p�#XvRlS�*������7~:��Tڱ=�������/CP���ݥfk�R,�T<E���v�F��|�T_�'���䄨
-�-���)����o�����Q�}+���J�{�'q�cS�kGٹ<��k�'z`�d�{N�
-D��^�N0<~����Y���}�x3A��ߵ���|d�1W����>G\N����x���4���r�++@.���P����s��c����V������-���m�V5�8������J�Zf<�D�Y��orlCώ������ԝ|��ǐ�؞,<9Yc,��"�,���/��C���<Q}�b5��Z5�#�VN���m��ޣ�Oktat�ͭ����x���g�f,�5�5���Ғ��̽oU����(��V��(!V���Ql��Q���S�v��W�催��!��=Y����pU���rЧ�8K��|7���	J�(�R;A�;��6knb>R=h�k�Z�o)������l�������#樗:�R�'RAxMm���)m��-�I`���-C�9�R�m����p|W%�����y��Ĉ�=��qXg6�&�_5j�dD�cS ��`�)K��}�Z=J�g�i%r,z[e���5�Q�n�Jѽq���95�M����W���W�
-�����`�$l�6"'PU�Kio)叏�o�m�MĬ-i_a��㴰�(��3����3�9�R*/�H�n�fR��«h�^��b��dw���±�ڃ�X�_��8t�*�ʇ�5F����,�B��qށ�F%��z@�A�s�ֳ�k�������\���6���|��O�J8��]B����Qy�P	Q�%.�����._X�A�R�.���~Ͳ��X�y�O��������ec��Z�aHʢ�x�B01�􁽅�S�L���ρ�[8�P�.��S��V���w���
-1FQ�|�v���݁�*�?���R]f)��#������T���(Y �Q��;����F�2��8���
-AIU�"�s�C��>���?hᵤy	M���j�j?A����<���7�N��Z3��&�y�8}z���U��,��^���?;��������4ie�gN�����tֱ����O��.^_��S�dۊ��Qbe։��m�:ۚ�I�P&Q��L����'�N����
-�
-xZ�F�*�/�Z���6�-��{�ɰ叉�����0[�m;pIQ����ߛå��ޠf1�������6�{#�['
-'�����_>�3�V郮�z����3��hIG�%�p�N?;**,4Y���K�]e���`�񠞐Fތ),����e�-��u���,W��)�R̤��~�?�����l�D���O��q��-y^ɕ^GD��/:��%���ecL�A<㾹kG��{����i��~8Vx@6��!u��=�������Ԯ2��/ao�FU��n}�5�N
-�����Pw�5��E���bG�O�ۜ<\�>���s&Ϩ|��z]6=��0���G���ɝ:s!#RivT���[ڮq$����E���q�����.��������^��i�����40%�0�,�Sq���g&E�߷���BR0�H\샡��,�-�N,G�+�_U��d���6��4䔪׹e�9{y���|員�����XA��P�w+*Ô�Ȭ��\��ĕ����E)؏8��j2%�m�y���?��E�-r�<�ou��t�Y�XS�\מN)����5U…��nj�֒@=a��Ӗ���E:/��ᝧvy)u�Q�R1k&�4W;K푂��&��h˴
-�c#jw�����w��`���R�}����I��%��J��2]S��4^7>H�#��*��om=�tc��+�<8�ͭ:5[�����ɠ�P��b_
-�
-tM�2s���u��L��ۻ�_��D�l>.U|r����*�k�[�"^�M�5�y6�#�k�^~�q�U�4n�׸��&XC�r�8_�~���ɌT:n^;>�H$�cS�L��8�3���a��_���pd�_5�02�$IK��v�%B.A]՞��:LwL�kQfc.m��'��fV�i3-h��Q�o�$�>Nl��%H�9�.)��U����wJMVϥ���.R���L�04�|r
-��*ᷟ����V���Y�0�
-݄��
-���[o�ƴ���+gR��K_� d��QW?���lv[CT��?8�νf9�F��%Q�������c%����x�_�G�������q�-�ㆀ{�-~���kn=!Ю5����=|{~����`w�t����eР����6q�s�5W8�J�rc"γ�\!�@���0�e��!ҰTV.�Zl�_/SOd���%ͅ%v�:q����3
-HMƵ�s�`~�+�����Cq�� ������r���,E9V<!w������)0w������D��B�΄��`�9
-endstream
+x��gXS۶�DzUTD`!EPH���"5 ���*Ei�	i"%H�&E�����^�+M:������o�9��k=01�PC����Q4��R+�(����rT0���!���
+)fѿ�+;�=(k����v����$d56��U��ұ�d����������~�ӝk�z<Wt�����n���[�a댗��èʆ��rߺ��~һ��un����HӀ;����c��ۏ�9�+�3�b;�LzĝW��j{.��M9�۾�.1yG�Z$o(��r�hs-�wQH�	�
+j4�3�6�D�H8_rj!F 
+���p:���c
+�f�u����֯�l���8l&���{���_��[5�g��+~tض�v�4���o���� ������J�V���F�T��k�a��gQ�s2&����T\ޝ��O2��G������d#��Rbv���:�$WH��U,�[-��������C�\�$<���1*��r���X��z�k�R�N���+ϫ����`D(�����I%ag{ۉ�:V�㒙�a"���Z�rB���/&�F����XA�j=8whA��.xX��5�.Km\�6n�wVc,�i�$� �&�5I�X�[9�`�V���N��&|5;o�u��>����Ý,�����K��H�!|����_��K�x����%���-��IO�Ǵs>i�ٳ���X2����l������q|����6����r�·�Ntq˙�	���nB�ys�Ϲm����1��6�Q���ؕ�=���
+��l$�p5�6�?�"���N�%
+w�о���a>x�D��=�um��2�G>�?B<„V��1u96u�US4�n
+��gآmbHR��%djm.�_0��)�g����sҘs�
+8�ܮ᪵
+'9\�\�>ܡ�T�T4U��p2�	K����8�l�2�p:2ٺ�Q^�6�r�y]�m���4obn�R
+�R�r&�����
+յh�${E��}�덕��壋��ӳ�����F�@]��kV�51j�n�T�����+]�-�yi)�:DQ��=�ջV�4�����p��.6�-��ө��#�>�h��CC����~�
+��[b
+����vګr���E���E�ݲ@�|�1� �y�)[� 
+�9�����υ������z�t��_��@[l
+�5�ܮQ7�h~�����ɶ�<��ŏh'���<�m���ڈ5���p�y�.;<��s�l��,�S���#�P�UZ�q�9!���N������9VI��1w�Х�܅�:�Yr^��sY����a�S�]E�9����[E:B�FGg��0U��5����;j>�Xv�/��~+��M����`��lL�4x�Cq���ݝ(?a9T�&���&��DƢn'�D�7�˹3�ܯ�Ҟ�����6�iv=�x�Ga»tB��H+SU${Y�c~znR��`5����M���%\�g1<����������G��7��95Wk�FVt���K����){F�f��Ә&��
+�
+����R5O���k#5�����řT���ho���#�}^ˍ�:�+�
+�gv,[��u®̵͊ɽ�r��H��m��Dw��S�4cd�a?�\:5h*yTp{����_|�R������TNh�(m�����x�x@�5�B&���	\��&V�6�W%�6�sU0+p<�&�&³"��:��ɧ�|Яe5l�+�;�+:�9bPN�}���+��ٲ��k����4�T6��¯�?�k�*�c?�4���p�ry�!�_Au��#}��\j�o���|�?�0������,�ژ��?���R�1�81��w�'�+ק��	z���:����E�96�e����%�v6��S�΍s��y��F�336G=��7�����L|��{k�n�y���N��a��ù�o��-��B@.B�3�͋���*tۨ��ې�]���=XjxvW�TBM�CW͌�1;�m�{�	Udz�Bf{Ďar�K�N������ڎ-�<�ċ�&��㽨���a����>�yx��:�8��ڂ���}?���5˪z������������G5��-���&i?��������/��s�ndstream
 endobj
-35 0 obj
-<<
-/Type/FontDescriptor
-/CapHeight 850
-/Ascent 850
-/Descent -200
-/FontBBox[-4 -235 731 800]
-/FontName/PQEIII+CMTT10
+9 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 77 0 R
+/FirstChar 44
+/LastChar 120
+/Widths 78 0 R
+/BaseFont /ZCHLIL+CMR12
+/FontDescriptor 7 0 R
+>> endobj
+7 0 obj <<
+/Ascent 694
+/CapHeight 683
+/Descent -194
+/FontName /ZCHLIL+CMR12
 /ItalicAngle 0
-/StemV 69
-/FontFile 34 0 R
+/StemV 65
+/XHeight 431
+/FontBBox [-34 -251 988 750]
 /Flags 4
->>
+/CharSet (/comma/period/zero/two/seven/eight/at/J/a/e/g/i/k/l/m/n/o/r/s/t/u/x)
+/FontFile 8 0 R
+>> endobj
+78 0 obj
+[272 0 272 0 490 0 490 0 0 0 0 490 490 0 0 0 0 0 0 0 762 0 0 0 0 0 0 0 0 0 503 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 490 0 0 0 435 0 490 0 272 0 517 272 816 544 490 0 0 381 386 381 544 0 0 517 ]
 endobj
-34 0 obj
-<<
-/Filter[/FlateDecode]
-/Length1 1874
-/Length2 12070
-/Length3 533
-/Length 13138
+77 0 obj <<
+/Type /Encoding
+/Differences [ 0 /.notdef 44/comma 45/.notdef 46/period 47/.notdef 48/zero 49/.notdef 50/two 51/.notdef 55/seven/eight 57/.notdef 64/at 65/.notdef 74/J 75/.notdef 97/a 98/.notdef 101/e 102/.notdef 103/g 104/.notdef 105/i 106/.notdef 107/k/l/m/n/o 112/.notdef 114/r/s/t/u 118/.notdef 120/x 121/.notdef]
+>> endobj
+5 0 obj <<
+/Length1 1069
+/Length2 4336
+/Length3 532
+/Length 5041      
+/Filter /FlateDecode
 >>
 stream
-x��UX�����Ch�	�����%Xp�58	$�3��7��������ʸ������X��r����sh�B����r�!���B����������_��y1��:xx3r-��g�(�F^��,5�J<�؏�^ӭ���?��u-gyH�.ݝ߳t�>c���
-q��:�tc�l�W
-���Ϊ1p�zъ�:��x�i��l3p�^�]R�K"���� ͺG蕐|<���F���������.w=�����k�E��nA@�Nbe�s�)+&�(�.�B�e����o�C���ғU'-�l6������g*Qž��Q0S.��ﷆ�|U{1kCzQ�����Ɖ���m�\�>c
-�8�pM�aZ�!hZ����M����&_b��E8���)d�ٲ!C����M¸OvL�Z�ݭ��P���Y����������g7��+3��T|HG%ߌ�E
-+�w�T�T�>�2ٽ},:{g�
-��\D5Tdc��.���ITx����De?E�v2�Н���7Ȫ�o�N- Y64���G�@H�p���-T� iW�:r����������r���������p;�(Y��FXfi8ܽ�]��?��|4�����������d԰K�ƓYϏ\2b�"�Kґ=�,�T�Gs��I���	q��.���9I����nI
-���du>���g6ny��gq�@���ƄM4�$l7����{��F����̒.�C$?�l��,ɕ�l8�?-=4�$`<kl��Z8B_i4�0����*k�5�f�����;���lcl]\'���s*����E�À��F�
-�dzWT�^�tƐOHC�����5	����ž�?Gg\a>�8G&��-�>��V��G��<��Gi����Q���9+t����c����>�����a�߼w���+��%�m%Vް_` _R���m-ڲ�	�"�ߋ�79��ԺWpU��X_����;�)����FԽ����M7�,�%��:�t<�LS�{D[$��
-�	������6J�u�z��������]�8񀲙mp��4}g+�֯�����-��	�����sq��.]m2Y����s��U�G0��!D��E����������F�#�����n�����2��{�*�~���d>�T,��S������}�^�n�����J��(�dSf���Zh�܎ޑ5֐�KD0�.g�Z���Vf�)@%�oQ������L�U*��/$J��!�i�J��g��X�R-(��&�׍��v;%��GE����C����xN������_��A�{���m_��J�f�!����-��3��7-IƁ��#6�f1U���ohm5�®L%���Y���$O���*�"��郩(t��%���A�!*1�����ӎ��vn�]F���e�4Q�6,��n������Ϸ�1��9�R�0K{ϊƄ�ϩiZ����l�'怖�w�:���<�}�T�Y(t(P��o��\X�ܮ�8�����P1'��M�g'f��8�Ho��NH����0��;�[;6f@~����4S�!��\#�l�z�V�H'¶
-�]1�������>U���A�-z>@���Qr���?��o���ʣׅ.���-HPХ�= ȾN�ü�z�s���@>4"DԊ���v���W�ֹ�[�g|#��|S
-W��o�`CI/���@$Ь`�@�����`u��WO.EPϠ������S�z}��Z�]�5�|q�gl8��W���ѻ+jR޽�i/"��Ć�!.�����Dr��[A�z��j�\�8{�zjˀb�,,����2RՐ0L<���.d�-���"�S��6"]��~o���~�`��<2�������]��V%�4�͛�g��~�����#���zzc褌.+��iJ|�lm�[�6l�]e!C����H��mІ��ǧ�����y	��[��[vG�?B�H����bd��W��rg�1Wq�f�#�đ����.<�;���h�F䕰v�	��P)�'�_��E�2JFD��6̫@��$�����@��J]W��|�b��S�2���������?��cQ������k�#��w��뗋A/=[EÁ���>[-^+_���������Ӓ"����dd���p���J%�v(�W'���`��O&�>�!#7���Zu�p=���3`)�?fV�a�)6�>���;
-�N�c
-��W��V���n|&!������S��Bd�v���);�{�!
-�JW�E�470��Z�5�;�#{<������d*�1�����2h�ŧ��l;]W8Z���Ųٌgs��D����ք��{��t�w����{Zٔ]�8�q�a����w���t���-�3ӇDͨub��ƪ�KDs����[K�N�IJ|�;1N4pmL�/���/�)����^�l7��,�W~�|-8��_���O�0��\<m�"��S8�wI�%��n�F�63��[~�
-��à�0��^��������;bo���ؤ��"�
-?���`�{��������܍/�1=�<�
-_&РQ��VT�?'O�<�ڴG�Z��;ϴ51Tz+s����"Y������X�#\��m�S.3Ȧ�����3��
-�Q�qh�?/�tE��CY<4Z̤_Xй����*{���*����wNHZ�O��U>�5�WrM.8���X(���J��d���H�,Q}��\�1��|jq���v�Q�V����M3��j���p��7<�~
-[#�2H���M�-�t����[����7�;�SE�����CQ���<"U~r��1��?,X�X��B�uH}��=�
-O_`�mY�T���j���y�:F�Q�{Ӽ
-�����Ee�1J}��l�T� ;�^%g3?���m�}�=�Kp��>=؍���4�TU���2��-R�B1D��3�����vjx��6��k���/+,�������D�а��V8Z�}�+�u5�V	/�]��x���s
-�}�zP#4���Ϊa���(Q9���g����9WwB���=�>wN��JE�K�1��/.��~~y`�.!�B���/N.�C�-��4����}���n?�.� �py��/�̻޲t'���n���Sb����ud�̣?r���1�)��@�f��	\�͟���ȹT6�ܧ���;w7~ɖBo��Z��W� $(Wpa��9�R��������,"JQl������|��9�3�G��IF�=�������+�2͉=<�t�_��n��)�mj���I���^I�H��(F��7��ޖ��x��%��(�
-���������8|��-����9W�Ƞ*�T�Fԁ!�N���gd	���b{��Z2�i�a������PŌ~��7:����tL�-V��s!TMD���Ip��s������~�SE�UD�Ȗ�ӈX5��Q�X��.O�5��pD�^�#���S���v�i��g�ͦ�@�"�n?_�O�����Z)�����c+�П�l���gn$?�e��ĠB�GB'���OV�.^��$�Z$
-ɨ�9K)ab��=�2�#��X�K����N'�Y��&�R��U�=څ[m�3���Jd�P��/4E���P�S
-���"R����r����6l��J����d�'�X��EE���URJ�8b��)�?'��-�]>09�9Lճdأ��y���lܙ�Y_Q����������}V@������{8ñ���UNrta�wVt(q���,a�>-]�G�Mm_�W+���O�-�}�Z>)�K	ۂ[G���C_ne%j ���[oK)Wÿ����T��x�U"���
-�{2u���Z���4��13����5SJ�g�K[�ĝ�OZj&c9����y�B"GkHL�
-�N3
-��
-k�$�����TM�6I������5z\ڼ;v0e!^hs��"��O�����c�h�"����|ˤ��7��9���({�>���M����h��އǧ�bܮ����c��?��-s��G�<�W�-O��
-ad�O���MF����y�xǰ�}*q�����?E�`4���He��a9�p�+*�.f�������������0(H�#��v=Ҋ$d��<��%��n���-������9ch�7�_����C@\������-��(c������-N�`� cz���~����EQ����μ�$�ԐI}I 1����;�xa��-�HT�7a��P�H�����]��~L���E�V�������z���}\����������vQ2�ai�R\��ߊ���W%J�X�-7H�������9
-c��2Q�-endstream
+x��gXk���JU@ġ#-	%�(һ�4)R"	I�7EA�JՀ4Azo
+��t� �����?s���}f͚k��K�T���T��!bY@�@�4||�$�+�Ũ���+#��Ny �� ��h�Š�Ҏ��%�:�q5w4Z��g��#
+wF����+C)(+��������%Q9�̮|��_ض-��r�!�Jw����;��,��.��K���	=|����f��+>�%i����M��7�_j�x���\(Ы*�Μ𗑶4`Qo��)'����ji�^�ƈ@���y�O�NM�'�jq2g0kR�<��@�&��]Ҋ�`���G���R̊�<h��������aw�ɉ͚���(_��>���-6t��p.̺��3s�*�ILn�6�����z J�B�H;x�bLf������x�����)�t���<�m�/c�vم��-3|�{>Ѳ�Cm�h^��g�]s��A�����7zx>}��v�.���J�w9�Sy7��BC�9�>O�]���c�ظ�����H"}���)����|)�4�%^��Ӂ:d2I�ᢏ�a�1�\n���&��	g�<P+��E��z6��2�R~ѴkY�!�=v^=
+K�G��Ә����l,��ݙ)-����H����/R��U�?/>����p8�8,�u���2h�OT�Щ;��������'P�҉n7�7��'hy<�~𚏲ו�Ձ�Q�j��Űg�,ç�a��"7��s&�^�f�8�[�n����m6�/.p����Q&��ᄥn���u��9��_��c%9�څ��w�ƚ{���+�o���.|\�uql�Y�nё~~(��L�0x�e�ɸ����5� ����5�꓆��G�*c=�R���_O���p?�Ց���0<a+��eD���v�F
+���m���2^8�)��G{�U�;�1��[n^������50��{�v2�~Z��)�{�n	��X���P<�S���a��|'�B�/[T���^��H��GJ!�y�5���6���l�Rr���o�f�)�Lլ��3�`^�B�T�"��+s2>>ٛ�L6�އ���ש���-cu�����e�Qڡ�����ڳͷ�̘$���g�FB]�����)8��ޡն���3	}4.�=�Ћ2~#�2QS���5GQVB�.�Oة�O����|{eG���v�B�==���9—����qSU�/������:M����;�b���W�@��y���h^�:�~e�n\������uD�:�vB��G:�ޔsu����'���}I��]�fs����o׈\Z�M=uW�g�^�3#}:o×��G�U65^�oj%Hw����<�����/Y0�����fs�J�����F�xn7ˏ\8Ŕ�����u
+����m��N�)L
+qvt�<��r��Jw�Fz=�?b�񫦊+�(�$��1�ᰶ����.(g_��ˑY&���3	������.����q�v���xT5�%}���1�)�N�0E#4������^}lݢ�|4�{����}��l^�����S����ؙ;�լL��"o��f{]b�����J��R�T�5Es��^��oUt�Sh�M�_l��'��?yn.��C+�e].}�G���W����8�H�f$K��P���ʶ��~�|���{����M^����,��������͔f�t�q�o��=�����H�>S'X�R�ky�܎�|�+w�HO��Z��pS�p�j��:�����1�|�{Z�]G����/_;���r)ڵ>O����YH,����/j;6l_f]g�>,t��
+�P\{��9Z^��Z‹'h��(��3�Y�šF����˒�*k�x�<~.7O%��M-����������֪������*��S��O^�B�^�?ס�U�X���K�������,o��P�~�!�X�ӯi7��mR�F�%����A�Q���Z�k�-h��O�dobj
-42 0 obj
-<<
-/Type/FontDescriptor
-/CapHeight 850
-/Ascent 850
-/Descent -200
-/FontBBox[-29 -960 1116 775]
-/FontName/NENDNC+CMSY10
-/ItalicAngle -14.035
-/StemV 85
-/FontFile 41 0 R
-/Flags 68
->>
+6 0 obj <<
+/Type /Font
+/Subtype /Type1
+/Encoding 79 0 R
+/FirstChar 39
+/LastChar 118
+/Widths 80 0 R
+/BaseFont /NPUWBR+CMR17
+/FontDescriptor 4 0 R
+>> endobj
+4 0 obj <<
+/Ascent 694
+/CapHeight 683
+/Descent -195
+/FontName /NPUWBR+CMR17
+/ItalicAngle 0
+/StemV 53
+/XHeight 430
+/FontBBox [-33 -250 945 749]
+/Flags 4
+/CharSet (/quoteright/hyphen/A/G/J/P/S/T/U/a/b/d/e/i/l/m/o/p/r/s/t/u/v)
+/FontFile 5 0 R
+>> endobj
+80 0 obj
+[250 0 0 0 0 0 302 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 693 0 0 0 0 0 726 0 0 471 0 0 0 0 0 628 0 0 511 668 693 0 0 0 0 0 0 0 0 0 0 0 459 511 0 511 406 0 0 0 250 0 0 250 772 0 459 511 0 354 359 354 511 485 ]
 endobj
-41 0 obj
-<<
-/Filter[/FlateDecode]
-/Length1 777
-/Length2 594
-/Length3 533
-/Length 1156
->>
-stream
-x�U�L�Ju�+���Rp�44P0��u.JM,��I,I�R0��4Tp,MW04U00�22�25�Up��,��Q���2Wp�-�N��H���������ZR��������Z�ZT����eh����\������ǥr�g^Z��9D8��-@W��T*���q�mK��dgaq��99~�� ��!����S	U��[PZ�Z���Z���4<�Ԕ�\tYϒĜ�Ǽ�]C=cS�Df�[fEjJ@fIr�BZbNq*X<5/��;D���Y�ـ����ʂT�r0��SQf�B�����!P!��h����d���)$%VrS�g�Pm�����Z��Zt��^^~	P�0lj���@�������W����,t-̀&�)���֢*�,,M�500�0�x-���(5�������65�"5�k��Y�_\U
-��
-�ԣ6J�������v�sO��酹�֜9����w���9��ק��⼒���[�ͽ����jI��.������Ee��~�?v�PE_:�S�۹O�Z��:}�Ӎ�9N���^�������Y�mX%W�؟��n�����+���?�ɚ��s���M='�S�|_�o�͸���Ôf��/h�l�������o��7��������������m�aس���N���NEU����}�o��m�ƾ3����_�!��3��/[S�}�e�����w\�����\��,����6V��5]fk��61|Q͟�B����}���K����W(��,�暕-������-VɎe�=k��υ
-:~�������Wo����7#[H���K�S����Z��O����g��<�i@!�`X����XT���X��-endstream
-endobj
-1 0 obj
-<<
-/Creator( TeX output 2007.04.23:1418)
-/Producer(dvipdfm 0.13.2c, Copyright \251 1998, by Mark A. Wicks)
-/CreationDate(D:20070423141904+01'00')
->>
-endobj
-5 0 obj
-<<
-/Type/Page
-/Resources 6 0 R
-/Contents[28 0 R 4 0 R 29 0 R 30 0 R]
-/Parent 70 0 R
->>
-endobj
-32 0 obj
-<<
-/Type/Page
-/Resources 33 0 R
-/Contents[28 0 R 4 0 R 37 0 R 30 0 R]
-/Parent 70 0 R
->>
-endobj
-70 0 obj
-<<
-/Type/Pages
-/Count 2
-/Kids[5 0 R 32 0 R]
-/Parent 3 0 R
->>
-endobj
-39 0 obj
-<<
-/Type/Page
-/Resources 40 0 R
-/Contents[28 0 R 4 0 R 44 0 R 30 0 R]
-/Parent 71 0 R
->>
-endobj
-46 0 obj
-<<
-/Type/Page
-/Resources 47 0 R
-/Contents[28 0 R 4 0 R 48 0 R 30 0 R]
-/Parent 71 0 R
->>
-endobj
-71 0 obj
-<<
-/Type/Pages
-/Count 2
-/Kids[39 0 R 46 0 R]
-/Parent 3 0 R
->>
-endobj
-50 0 obj
-<<
-/Type/Page
-/Resources 51 0 R
-/Contents[28 0 R 4 0 R 52 0 R 30 0 R]
-/Parent 72 0 R
->>
-endobj
-54 0 obj
-<<
-/Type/Page
-/Resources 55 0 R
-/Contents[28 0 R 4 0 R 56 0 R 30 0 R]
-/Parent 72 0 R
->>
-endobj
-72 0 obj
-<<
-/Type/Pages
-/Count 2
-/Kids[50 0 R 54 0 R]
-/Parent 3 0 R
->>
-endobj
-58 0 obj
-<<
-/Type/Page
-/Resources 59 0 R
-/Contents[28 0 R 4 0 R 60 0 R 30 0 R]
-/Parent 73 0 R
->>
-endobj
-62 0 obj
-<<
-/Type/Page
-/Resources 63 0 R
-/Contents[28 0 R 4 0 R 64 0 R 30 0 R]
-/Parent 73 0 R
->>
-endobj
-66 0 obj
-<<
-/Type/Page
-/Resources 67 0 R
-/Contents[28 0 R 4 0 R 68 0 R 30 0 R]
-/Parent 73 0 R
->>
-endobj
-73 0 obj
-<<
-/Type/Pages
-/Count 3
-/Kids[58 0 R 62 0 R 66 0 R]
-/Parent 3 0 R
->>
-endobj
-3 0 obj
-<<
-/Type/Pages
-/Count 9
-/Kids[70 0 R 71 0 R 72 0 R 73 0 R]
-/MediaBox[0 0 595 842]
->>
-endobj
-28 0 obj
-<<
-/Length 1
->>
-stream
-
-endstream
-endobj
-30 0 obj
-<<
-/Length 1
->>
-stream
-
-endstream
-endobj
-4 0 obj
-<<
-/Length 33
->>
-stream
-1.00028 0 0 1.00028 72 769.82 cm
-endstream
-endobj
-74 0 obj
-<<
->>
-endobj
-75 0 obj
-null
-endobj
-76 0 obj
-<<
->>
-endobj
-2 0 obj
-<<
-/Type/Catalog
-/Pages 3 0 R
-/Outlines 74 0 R
-/Threads 75 0 R
-/Names 76 0 R
->>
-endobj
+79 0 obj <<
+/Type /Encoding
+/Differences [ 0 /.notdef 39/quoteright 40/.notdef 45/hyphen 46/.notdef 65/A 66/.notdef 71/G 72/.notdef 74/J 75/.notdef 80/P 81/.notdef 83/S/T/U 86/.notdef 97/a/b 99/.notdef 100/d/e 102/.notdef 105/i 106/.notdef 108/l/m 110/.notdef 111/o/p 113/.notdef 114/r/s/t/u/v 119/.notdef]
+>> endobj
+25 0 obj <<
+/Type /Pages
+/Count 6
+/Parent 81 0 R
+/Kids [2 0 R 27 0 R 33 0 R 39 0 R 42 0 R 45 0 R]
+>> endobj
+50 0 obj <<
+/Type /Pages
+/Count 5
+/Parent 81 0 R
+/Kids [48 0 R 52 0 R 55 0 R 58 0 R 61 0 R]
+>> endobj
+81 0 obj <<
+/Type /Pages
+/Count 11
+/Kids [25 0 R 50 0 R]
+>> endobj
+82 0 obj <<
+/Type /Catalog
+/Pages 81 0 R
+>> endobj
+83 0 obj <<
+/Producer (pdfeTeX-1.21a)
+/Creator (TeX)
+/CreationDate (D:20070628000323+02'00')
+/PTEX.Fullbanner (This is pdfeTeX, Version 3.141592-1.21a-2.2 (Web2C 7.5.4) kpathsea version 3.5.4)
+>> endobj
 xref
-0 77
+0 84
 0000000000 65535 f 
-0000090280 00000 n 
-0000092043 00000 n 
-0000091696 00000 n 
-0000091896 00000 n 
-0000090444 00000 n 
-0000008923 00000 n 
-0000028122 00000 n 
-0000027938 00000 n 
+0000002779 00000 n 
+0000002664 00000 n 
 0000000009 00000 n 
-0000033601 00000 n 
-0000033415 00000 n 
-0000000985 00000 n 
-0000039334 00000 n 
-0000039145 00000 n 
-0000001886 00000 n 
-0000046799 00000 n 
-0000046611 00000 n 
-0000002816 00000 n 
-0000062083 00000 n 
-0000061897 00000 n 
-0000003717 00000 n 
-0000065044 00000 n 
-0000064858 00000 n 
-0000004665 00000 n 
-0000068015 00000 n 
-0000067829 00000 n 
-0000005649 00000 n 
-0000091796 00000 n 
-0000006633 00000 n 
-0000091846 00000 n 
-0000008825 00000 n 
-0000090546 00000 n 
-0000012202 00000 n 
-0000075561 00000 n 
-0000075375 00000 n 
-0000008984 00000 n 
-0000009711 00000 n 
-0000012114 00000 n 
-0000090727 00000 n 
-0000015475 00000 n 
-0000089011 00000 n 
-0000088816 00000 n 
-0000012264 00000 n 
-0000013198 00000 n 
-0000015376 00000 n 
-0000090831 00000 n 
-0000017841 00000 n 
-0000015537 00000 n 
-0000017797 00000 n 
-0000091013 00000 n 
-0000019992 00000 n 
-0000017903 00000 n 
-0000019926 00000 n 
-0000091117 00000 n 
-0000022074 00000 n 
-0000020054 00000 n 
-0000022008 00000 n 
-0000091299 00000 n 
-0000024172 00000 n 
-0000022136 00000 n 
-0000024117 00000 n 
-0000091403 00000 n 
-0000026107 00000 n 
-0000024234 00000 n 
-0000026052 00000 n 
-0000091507 00000 n 
-0000027876 00000 n 
-0000026169 00000 n 
-0000027810 00000 n 
-0000090650 00000 n 
-0000090935 00000 n 
-0000091221 00000 n 
-0000091611 00000 n 
-0000091978 00000 n 
-0000092000 00000 n 
-0000092021 00000 n 
+0000090585 00000 n 
+0000085270 00000 n 
+0000090430 00000 n 
+0000084456 00000 n 
+0000079003 00000 n 
+0000084301 00000 n 
+0000078094 00000 n 
+0000070609 00000 n 
+0000077936 00000 n 
+0000069279 00000 n 
+0000054466 00000 n 
+0000069122 00000 n 
+0000054122 00000 n 
+0000051739 00000 n 
+0000053967 00000 n 
+0000051395 00000 n 
+0000049007 00000 n 
+0000051240 00000 n 
+0000048176 00000 n 
+0000041916 00000 n 
+0000048020 00000 n 
+0000091377 00000 n 
+0000005512 00000 n 
+0000005394 00000 n 
+0000002916 00000 n 
+0000040611 00000 n 
+0000027165 00000 n 
+0000040453 00000 n 
+0000008395 00000 n 
+0000008277 00000 n 
+0000005605 00000 n 
+0000026849 00000 n 
+0000025464 00000 n 
+0000026692 00000 n 
+0000011229 00000 n 
+0000011111 00000 n 
+0000008535 00000 n 
+0000013624 00000 n 
+0000013506 00000 n 
+0000011310 00000 n 
+0000015618 00000 n 
+0000015500 00000 n 
+0000013729 00000 n 
+0000018279 00000 n 
+0000018161 00000 n 
+0000015723 00000 n 
+0000091485 00000 n 
+0000020295 00000 n 
+0000020177 00000 n 
+0000018360 00000 n 
+0000022831 00000 n 
+0000022713 00000 n 
+0000020400 00000 n 
+0000024482 00000 n 
+0000024364 00000 n 
+0000022924 00000 n 
+0000025371 00000 n 
+0000025253 00000 n 
+0000024587 00000 n 
+0000027079 00000 n 
+0000027056 00000 n 
+0000041422 00000 n 
+0000041073 00000 n 
+0000048729 00000 n 
+0000048434 00000 n 
+0000051641 00000 n 
+0000051606 00000 n 
+0000054368 00000 n 
+0000054333 00000 n 
+0000070109 00000 n 
+0000069725 00000 n 
+0000078642 00000 n 
+0000078396 00000 n 
+0000084930 00000 n 
+0000084713 00000 n 
+0000091060 00000 n 
+0000090835 00000 n 
+0000091587 00000 n 
+0000091654 00000 n 
+0000091705 00000 n 
 trailer
 <<
-/Size 77
-/Root 2 0 R
-/Info 1 0 R
+/Size 84
+/Root 82 0 R
+/Info 83 0 R
+/ID [<0005E6093B0F959C8EA0BF96414DD1C4> <0005E6093B0F959C8EA0BF96414DD1C4>]
 >>
 startxref
-92138
+91908
 %%EOF

Modified: puppetor/trunk/doc/howto.tex
===================================================================
--- puppetor/trunk/doc/howto.tex	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/doc/howto.tex	2007-06-27 22:09:47 UTC (rev 10687)
@@ -74,22 +74,28 @@
 homepage.
 
 After downloading, you need to put the Tor executable to the base directory of
-this framework and make sure that it has the name \texttt{tor.exe} or
-\texttt{tor.sh}, respectively.\footnote{This is going to be configurable in the
-future.} Further, you need to have a Java Runtime Environment version 5 or
-higher installed on your machine.
+this framework or make sure that it is in the path. You also need to put the
+Tor Controller API classes somewhere. Further, you need to have a
+Java Runtime Environment version 5 or higher installed on your machine.
 
-You can then start the examples with one of the following commands:
+You can then start the examples with one of the following commands from the
+base directory of this framework, assuming that the Tor Controller API
+classes reside in directory \texttt{../torctl} (line break behind
+\texttt{examples.} included for layout reasons only):
 
 \begin{verbatim}
-java -cp bin
-    de.uniba.wiai.lspi.puppetor.examples.AccessingPublicWebServerOverTor
-java -cp bin
-    de.uniba.wiai.lspi.puppetor.examples.AdvertisingHiddenServiceToPublicTorNetwork
-java -cp bin
-    de.uniba.wiai.lspi.puppetor.examples.AdvertisingAndAccessingHiddenServiceOverPublicTorNetwork
-java -cp bin
-    de.uniba.wiai.lspi.puppetor.examples.AdvertisingAndAccessingHiddenServiceOverPrivateTorNetwork
+java -cp bin:../torctl/bin
+    de.uniba.wiai.lspi.puppetor.examples.
+    AccessingPublicWebServerOverTor
+java -cp bin:../torctl/bin
+    de.uniba.wiai.lspi.puppetor.examples.
+    AdvertisingHiddenServiceToPublicTorNetwork
+java -cp bin:../torctl/bin
+    de.uniba.wiai.lspi.puppetor.examples.
+    AdvertisingAndAccessingHiddenServiceOverPublicTorNetwork
+java -cp bin:../torctl/bin
+    de.uniba.wiai.lspi.puppetor.examples.
+    AdvertisingAndAccessingHiddenServiceOverPrivateTorNetwork
 \end{verbatim}
 
 \section{Example 1: Accessing public Web server over Tor}
@@ -221,6 +227,12 @@
 network.shutdownNodes();
 \end{verbatim}
 
+A typical output of example 1 might look like the following:
+
+\begin{verbatim}
+Request took 527 millis
+\end{verbatim}
+
 \section{Example 2: Advertising hidden service to public Tor network}
 
 The second-easiest example is to advertise a hidden service to the public Tor
@@ -297,6 +309,19 @@
 network.shutdownNodes();
 \end{verbatim}
 
+A typical output of example 2 might look like the following:
+
+\begin{verbatim}
+Waiting for 2 minutes and observing RSD publications...
+RSD published 38514 millis after first circuit was opened
+RSD published 38514 millis after first circuit was opened
+RSD published 38779 millis after first circuit was opened
+RSD published 100074 millis after first circuit was opened
+RSD published 100567 millis after first circuit was opened
+RSD published 100568 millis after first circuit was opened
+Exiting...
+\end{verbatim}
+
 \section{Example 3: Advertising and accessing hidden service over public Tor
 network}
 
@@ -394,6 +419,14 @@
 network.shutdownNodes();
 \end{verbatim}
 
+A typical output of example 3 might look like the following:
+
+\begin{verbatim}
+Request took 13808 millis from client to server!
+Request took 14851 millis for the rount-trip and 1043 millis from server to client!
+Exiting...
+\end{verbatim}
+
 \section{Example 4: Advertising and accessing hidden service over private Tor
 network}
 
@@ -491,6 +524,19 @@
 network.shutdownNodes();
 \end{verbatim}
 
+A typical output of example 4 might look like the following:
+
+\begin{verbatim}
+Successfully started nodes!
+Successfully built circuits!
+All RSDs published!
+Started server
+Handling event: APPLICATION_SENDING_REQUEST
+Handling event: APPLICATION_REQUEST_RECEIVED
+Handling event: APPLICATION_REPLY_RECEIVED
+Handling event: APPLICATION_REQUESTS_PERFORMED
+\end{verbatim}
+
 \section{Architecture}
 
 Though the examples show how to use the simulator, they do not provide insights
@@ -526,8 +572,6 @@
 private-network example.
 
 \item Fight the TODOs\ldots
-
-\item Complete logging and documentation for the impl package.
 \end{itemize}
 
 \end{document} 
\ No newline at end of file

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ClientApplication.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ClientApplication.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ClientApplication.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -3,7 +3,7 @@
 /**
  * The <code>ClientApplication</code> can be used to simulate simple
  * <code>HTTP GET</code> requests by a virtual local client. Therefore, an
- * address and a port are given wo which the client shall connect. Requests are
+ * address and a port are given to which the client shall connect. Requests are
  * performed by a background thread, so that multiple requests could be
  * performed at the same time.
  * 
@@ -13,9 +13,10 @@
 
 	/**
 	 * <p>
-	 * Arranges for the requests being performed by a thread in the background
-	 * and returns immediately. This thread will try for <code>retries</code>
-	 * times to make the request with a timeout of
+	 * Performs one or more HTTP requests to a previously provided address and
+	 * port. All requests are performed by a thread in the background, so that
+	 * this method may return immediately. That thread will try for
+	 * <code>retries</code> times to make the request with a timeout of
 	 * <code>timeoutForEachRetry</code> millis each. If an attempt is not
 	 * successful, the thread nevertheless waits for the timeout to expire. If
 	 * <code>stopOnSuccess</code> is set to <code>true</code>, the thread
@@ -32,6 +33,8 @@
 	 * is fired.
 	 * </p>
 	 * 
+	 * TODO may this method only be invoked once?!
+	 * 
 	 * @param retries
 	 *            The number of retries that this client will perform. Must be
 	 *            <code>1</code> or greater.
@@ -48,8 +51,14 @@
 	 *             Thrown if an invalid value is given for either of the
 	 *             parameters.
 	 */
-	public void performRequest(int retries, long timeoutForEachRetry,
+	public abstract void performRequest(int retries, long timeoutForEachRetry,
 			boolean stopOnSuccess);
 
-	// TODO we need some way to interrupt performing requests
+	/**
+	 * Stops all requests that are currently running.
+	 * 
+	 * @throws IllegalStateException
+	 *             Thrown if no requests have been started before.
+	 */
+	public abstract void stopRequest();
 }

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/DirectoryNode.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/DirectoryNode.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/DirectoryNode.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -3,37 +3,43 @@
 import java.util.Set;
 
 /**
- * A DirectoryNode represents a Tor process that acts as RouterNode and is
- * further a directory authoritative server for the (private) Tor network. It
- * inherits most of the configuration and behavior from RouterNode and adds some
- * directory-specific configurations and behavior.
+ * A <code>DirectoryNode</code> represents a Tor process that acts as
+ * <code>RouterNode</code> and which is further a directory authoritative
+ * server for the (private) Tor network. It inherits most of the configuration
+ * and behavior from <code>RouterNode</code> and adds some directory-specific
+ * configurations and behavior.
  * 
  * @author kloesing
  */
 public interface DirectoryNode extends RouterNode {
 
 	/**
-	 * Combines the node's fingerprint to a DirServer string that can be used to
-	 * configure this or other nodes to use this node as directory server.
+	 * Combines the fingerprint of this node to a <code>DirServer</code>
+	 * string that can be used to configure this or other nodes to use this node
+	 * as directory server.
 	 * 
-	 * @return DirServer string to configure a node to use this node as
-	 *         directory server.
+	 * @return <code>DirServer</code> string to configure a node to use this
+	 *         node as directory server.
 	 * @throws TorProcessException
-	 *             Thrown if a problem occurs when determining the node's
-	 *             fingerprint.
+	 *             Thrown if a problem occurs when determining the fingerprint
+	 *             of this node.
 	 */
 	public abstract String determineDirServerString()
 			throws TorProcessException;
 
 	/**
-	 * Writes the given set of routers (either directories or routers) to the
-	 * <code>approved-routers</code> file. This will confirm to directory
-	 * clients, that the given routers can be trusted.
+	 * Writes the given (possibly empty) set of onion router fingerprints to the
+	 * <code>approved-routers</code> file of this node. This will confirm to
+	 * directory clients, that the given routers can be trusted.
 	 * 
 	 * @param approvedRouters
-	 *            The set of approved routers to be written.
+	 *            The set of approved routers to be written. Each provided
+	 *            string must be formatted as
+	 *            <code>nickname 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000</code>.
 	 * @throws IllegalArgumentException
-	 *             Thrown if <code>null</code> is passed as parameter.
+	 *             Thrown if <code>null</code> is passed as parameter;
+	 *             however, if an empty set is passed, an empty
+	 *             <code>approved-routers</code> file will be written.
 	 * @throws TorProcessException
 	 *             Thrown if the <code>approved-routers</code> file cannot be
 	 *             written to disk.

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/Event.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/Event.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/Event.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -1,9 +1,9 @@
 package de.uniba.wiai.lspi.puppetor;
 
 /**
- * An Event is created for every state change of an asynchronous system
- * component, e.g. a Tor process or a client/server application running as
- * thread in the background. In contrast to <code>NodeState</code> or
+ * An <code>Event</code> is created for every state change of an asynchronous
+ * system component, e.g. a Tor process or a client/server application running
+ * as thread in the background. In contrast to <code>NodeState</code> or
  * <code>NetworkState</code> an <code>Event</code> cannot be a pre- or
  * postconditions for a method invocation. There is no prescribed order in which
  * events are fired by a certain process or application. Some events can be

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/EventManager.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/EventManager.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/EventManager.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -3,11 +3,11 @@
 import java.util.List;
 
 /**
- * The EventManager is the central place for a test run to manage asynchronous
- * events by Tor processes and client/server applications running as threads in
- * the background. A test application can either register event listeners to be
- * notified asynchronously about events when they occur, or synchronize with an
- * event by being blocked until the certain event occurs.
+ * The <code>EventManager</code> is the central place for a test run to manage
+ * asynchronous events by Tor processes and client/server applications running
+ * as threads in the background. A test application can either register event
+ * listeners to be notified asynchronously about events when they occur, or
+ * synchronize with an event by being blocked until the certain event occurs.
  * 
  * @author kloesing
  */

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/Network.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/Network.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/Network.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -16,7 +16,9 @@
 	 * Configures the nodes in this network so that they can run in a private
 	 * network and don't require public directory servers or onion routers from
 	 * the Internet. This configuration should be done after configuring the
-	 * nodes and before writing configurations to disk.
+	 * nodes and before writing configurations to disk. This operation can only
+	 * be invoked, if network status is
+	 * <code>NetworkState.CONFIGURING_NODES</code>.
 	 * </p>
 	 * 
 	 * <p>
@@ -55,8 +57,9 @@
 	 * TODO check if we have enough directory and router nodes to build a
 	 * private network? How many are required? 2 dirs and 3 routers?
 	 * 
-	 * TODO allow invocation of this method only in correct state
-	 * 
+	 * @throws IllegalStateException
+	 *             Thrown if network is not in state
+	 *             <code>NetworkState.CONFIGURING_NODES</code>.
 	 * @throws TorProcessException
 	 *             Thrown if an I/O problem occurs while starting nodes with the
 	 *             <code>--list-fingerprint</code> option, reading files from
@@ -68,16 +71,14 @@
 	/**
 	 * Creates a new client application, but does not yet perform a request.
 	 * 
-	 * TODO allow invocation of this method only in correct state
-	 * 
 	 * @param clientApplicationName
 	 *            The name for this client application, which is used for
-	 *            logging purposes only. May neither be null or a zero-length
-	 *            string.
+	 *            logging purposes only. May neither be <code>null</code> or a
+	 *            zero-length string.
 	 * @param targetAddress
 	 *            The target for requests sent by this client application. Can
 	 *            be an IP address, a domain name, or an onion address. May
-	 *            neither be null or a zero-length string.
+	 *            neither be <code>null</code> or a zero-length string.
 	 * @param targetPort
 	 *            The TCP port for requests sent by this client application. If
 	 *            the target address is an onion address, this port is the
@@ -99,9 +100,9 @@
 	/**
 	 * Creates a new directory node and adds it to the network, but does not yet
 	 * write its configuration to disk or start the corresponding Tor process.
+	 * This operation can only be invoked, if network status is
+	 * <code>NetworkState.CONFIGURING_NODES</code>.
 	 * 
-	 * TODO allow invocation of this method only in correct state
-	 * 
 	 * @param nodeName
 	 *            The name for this node, which is used as name for the working
 	 *            directory, for logging purposes, and as node nickname. May
@@ -123,6 +124,9 @@
 	 *            for incoming directory requests. May not be negative or
 	 *            greater than 65535.
 	 * @return Reference to the created directory node.
+	 * @throws IllegalStateException
+	 *             Thrown if network is not in state
+	 *             <code>NetworkState.CONFIGURING_NODES</code>.
 	 * @throws IllegalArgumentException
 	 *             Thrown if an invalid value is given for either of the
 	 *             parameters.
@@ -131,11 +135,11 @@
 			int controlPort, int socksPort, int orPort, int dirPort);
 
 	/**
-	 * Creates a new proxy node and adds it to the network, but does not yet
-	 * write its configuration to disk or start the corresponding Tor process.
+	 * Creates a new <code>ProxyNode</code> and adds it to the
+	 * <code>network</code>, but does not yet write its configuration to disk
+	 * or start the corresponding Tor process. This operation can only be
+	 * invoked, if network status is <code>NetworkState.CONFIGURING_NODES</code>.
 	 * 
-	 * TODO allow invocation of this method only in correct state
-	 * 
 	 * @param nodeName
 	 *            The name for this node, which is only used as name for the
 	 *            working directory and for logging purposes. May neither be
@@ -149,6 +153,9 @@
 	 *            for incoming SOCKS requests. May not be negative or greater
 	 *            than 65535.
 	 * @return Reference to the created proxy node.
+	 * @throws IllegalStateException
+	 *             Thrown if network is not in state
+	 *             <code>NetworkState.CONFIGURING_NODES</code>.
 	 * @throws IllegalArgumentException
 	 *             Thrown if an invalid value is given for either of the
 	 *             parameters.
@@ -159,9 +166,9 @@
 	/**
 	 * Creates a new router node and adds it to the network, but does not yet
 	 * write its configuration to disk or start the corresponding Tor process.
+	 * This operation can only be invoked, if network status is
+	 * <code>NetworkState.CONFIGURING_NODES</code>.
 	 * 
-	 * TODO allow invocation of this method only in correct state
-	 * 
 	 * @param nodeName
 	 *            The name for this node, which is used as name for the working
 	 *            directory, for logging purposes, and as node nickname. May
@@ -184,6 +191,9 @@
 	 *            the mirrored directory. May not be negative or greater than
 	 *            65535.
 	 * @return Reference to the created router node.
+	 * @throws IllegalStateException
+	 *             Thrown if network is not in state
+	 *             <code>NetworkState.CONFIGURING_NODES</code>.
 	 * @throws IllegalArgumentException
 	 *             Thrown if an invalid value is given for either of the
 	 *             parameters.
@@ -195,12 +205,10 @@
 	 * Creates a new server application, but does not start listening for
 	 * incoming requests.
 	 * 
-	 * TODO allow invocation of this method only in correct state
-	 * 
 	 * @param serverApplicationName
 	 *            The name for this server application, which is used for
-	 *            logging purposes only. May neither be null or a zero-length
-	 *            string.
+	 *            logging purposes only. May neither be <code>null</code> or a
+	 *            zero-length string.
 	 * @param serverPort
 	 *            The TCP port on which the server will wait for incoming
 	 *            requests. May not be negative or greater than 65535.
@@ -215,8 +223,6 @@
 	/**
 	 * Returns a reference on the (single) event manager for this network.
 	 * 
-	 * TODO allow invocation of this method only in correct state
-	 * 
 	 * @return Reference on the (single) event manager for this network.
 	 */
 	public abstract EventManager getEventManager();
@@ -244,11 +250,10 @@
 	 * with <code>false</code>. Thus, the maximum waiting time is
 	 * <code>(tries + 1)</code> times <code>hupInterval</code>. As soon as
 	 * all nodes have successfully opened circuits, the method returns with
-	 * <code>true</code>.
+	 * <code>true</code>. This operation can only be invoked, if network
+	 * status is <code>NetworkState.NODES_STARTED</code>.
 	 * </p>
 	 * 
-	 * TODO allow invocation of this method only in correct state
-	 * 
 	 * @param tries
 	 *            The maximum number of HUP signals that are sent to the Tor
 	 *            processes. Negative values are not allowed. A value of zero
@@ -261,6 +266,9 @@
 	 *            HUP signals. Negative values are not allowed. Typically,
 	 *            values should not be smaller than 10 seconds to permit Tor to
 	 *            stabilize.
+	 * @throws IllegalStateException
+	 *             Thrown if network is not in state
+	 *             <code>NetworkState.NODES_STARTED</code>.
 	 * @throws IllegalArgumentException
 	 *             Thrown if a negative value is given for either
 	 *             <code>tries</code> or <code>hupInterval</code>.
@@ -276,10 +284,12 @@
 	 * Attempts to shut down all nodes. The method blocks until all shutdown
 	 * requests have been sent and either returns, or throws the first exception
 	 * that has been observed when shutting down nodes. The method can be
-	 * assumed to return very quickly.
+	 * assumed to return very quickly. This operation can only be invoked, if
+	 * network status is <code>NetworkState.NODES_STARTED</code>.
 	 * 
-	 * TODO allow invocation of this method only in correct state
-	 * 
+	 * @throws IllegalStateException
+	 *             Thrown if network is not in state
+	 *             <code>NetworkState.NODES_STARTED</code>.
 	 * @throws TorProcessException
 	 *             Thrown if an I/O problem occurs while shutting down the
 	 *             nodes.
@@ -291,10 +301,10 @@
 	 * <code>maximumTimeToWaitInMillis</code> millis. The method returns as
 	 * soon as all nodes have started and opened their control port so that we
 	 * can connect to them. It returns a boolean that states whether the
-	 * operation was either successful or has timed out.
+	 * operation was either successful or has timed out. This operation can only
+	 * be invoked, if network status is
+	 * <code>NetworkState.CONFIGURATIONS_WRITTEN</code>.
 	 * 
-	 * TODO allow invocation of this method only in correct state
-	 * 
 	 * @param maximumTimeToWaitInMillis
 	 *            The maximum time to wait in milliseconds. A positive value or
 	 *            zero restricts waiting to this time. Negative values are not
@@ -304,18 +314,26 @@
 	 * @throws IllegalArgumentException
 	 *             Thrown if a negative value is given for
 	 *             <code>maximumTimeToWaitInMillis</code>.
+	 * @throws IllegalStateException
+	 *             Thrown if network is not in state
+	 *             <code>NetworkState.CONFIGURATIONS_WRITTEN</code>.
 	 * @throws TorProcessException
-	 *             Thrown if an I/O problem occurs while startint the nodes.
+	 *             Thrown if an I/O problem occurs while starting the nodes.
 	 */
 	public abstract boolean startNodes(long maximumTimeToWaitInMillis)
 			throws TorProcessException;
 
 	/**
-	 * Writes the configurations of all nodes in this network to disk. This
-	 * method is assumed to return very quickly.
+	 * Writes the configurations for all nodes in the network to disk, including
+	 * <code>torrc</code> and <code>approved-routers</code> files. This
+	 * method is assumed to return very quickly. In case of a private network,
+	 * <code>configureAsPrivateNetwork</code> must be invoked in advance to
+	 * this method! This operation can only be invoked, if network status is
+	 * <code>NetworkState.CONFIGURING_NODES</code>.
 	 * 
-	 * TODO allow invocation of this method only in correct state
-	 * 
+	 * @throws IllegalStateException
+	 *             Thrown if network is not in state
+	 *             <code>NetworkState.CONFIGURING_NODES</code>.
 	 * @throws TorProcessException
 	 *             Thrown if an I/O problem occurs while writing to the nodes'
 	 *             working directories.

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NetworkFactory.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NetworkFactory.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NetworkFactory.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -13,7 +13,7 @@
  * constructor using reflection. Currently, this is the only place where we
  * reference a class from the impl package.
  * 
- * @author karsten
+ * @author kloesing
  */
 public abstract class NetworkFactory {
 

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NetworkState.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NetworkState.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NetworkState.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -13,6 +13,7 @@
  * @author kloesing
  */
 public enum NetworkState {
+
 	/**
 	 * The configurations of the nodes in the network have not been written to
 	 * disk and can be changed. This is the initial state of a

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NodeState.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NodeState.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/NodeState.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -14,16 +14,17 @@
 public enum NodeState {
 
 	/**
-	 * The node's configuration has not been written to disk and can be changed.
-	 * This is the initial state of a <code>ProxyNode</code> or one of its
-	 * subclasses.
+	 * The configuration of this node has not been written to disk and can be
+	 * changed. This is the initial state of a <code>ProxyNode</code> or one
+	 * of its subclasses.
 	 */
 	CONFIGURING,
 
 	/**
-	 * The node's configuration has been written to disk and cannot be changed
-	 * anymore, but the Tor process has not been started, yet. This state could
-	 * be useful to review the configuration that has been written to disk.
+	 * The configuration of this node has been written to disk and cannot be
+	 * changed anymore, but the Tor process has not been started, yet. This
+	 * state could be useful to review the configuration that has been written
+	 * to disk.
 	 */
 	CONFIGURATION_WRITTEN,
 

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ProxyNode.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ProxyNode.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ProxyNode.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -3,31 +3,33 @@
 import java.util.Set;
 
 /**
- * A ProxyNode represents a Tor process that is configured as onion proxy, i.e.
- * to relay traffic from a local application to the Tor network and vice versa,
- * and does not route traffic on behalf of remote applications. It is the
- * superclass for other node types that extend the configuration of a ProxyNode.
+ * A <code>ProxyNode</code> represents a Tor process that is configured as
+ * onion proxy, i.e. to relay traffic from a local application to the Tor
+ * network and vice versa, and does not route traffic on behalf of remote
+ * applications. It is the superclass for other node types that extend the
+ * configuration of a </code>ProxyNode</code>.
  * 
  * @author kloesing
  */
 public interface ProxyNode extends EventSource {
 
 	/**
-	 * Adds hidden service entries to this node's configuration. This method can
-	 * only be invoked while the node is in state
-	 * <code>NodeState.CONFIGURING</code>. TODO Should this operation also be
-	 * possible while the process is running? We could easily change the
-	 * configuration via the controller.
+	 * Adds the entries for a hidden service to the configuration of this node.
+	 * This method can only be invoked while the node is in state
+	 * <code>NodeState.CONFIGURING</code>.
 	 * 
+	 * TODO Should this operation also be possible while the process is running?
+	 * We could easily change the configuration via the controller.
+	 * 
 	 * @param serviceName
 	 *            Name of the hidden service that will be used as name for the
 	 *            hidden service directory. May neither be <code>null</code>
 	 *            or a zero-length string.
 	 * @param servicePort
 	 *            The TCP port on which the service will be available for
-	 *            requests. This can be different for the virtual port that is
-	 *            announced to clients. May not be negative or greater than
-	 *            65535.
+	 *            requests. This can, but need not be different from the virtual
+	 *            port that is announced to clients. May not be negative or
+	 *            greater than 65535.
 	 * @param virtualPort
 	 *            The virtual TCP port that this hidden service runs on as it is
 	 *            announced to clients. May not be negative or greater than
@@ -43,17 +45,17 @@
 			int virtualPort);
 
 	/**
-	 * Adds the given set of DirServer configuration entries to this node's
-	 * configuration. Note that as soon as one DirServer is configured, the node
-	 * does not connect to an outside directory server of the public network any
-	 * more!
+	 * Adds the given set of DirServer configuration entries to the
+	 * configuration of this node. Note that as soon as one DirServer is
+	 * configured, the node does not connect to an outside directory server of
+	 * the public network any more!
 	 * 
 	 * TODO allow invocation of this method only in correct state
 	 * 
 	 * @param authorizedDirServerStrings
 	 *            A set of DirServer configuration entries that each contain one
 	 *            directory server that this node shall connect to. May not be
-	 *            <code>null</code>.
+	 *            <code>null</code>, but may be an empty set.
 	 * @throws IllegalArgumentException
 	 *             Thrown if <code>null</code> is passed as parameter.
 	 */
@@ -61,21 +63,35 @@
 			Set<String> authorizedDirServerStrings);
 
 	/**
-	 * Returns the node's name.
+	 * Adds the given configuration string to the configuration of this node.
 	 * 
-	 * @return The node's name.
+	 * @param configurationString
+	 *            The configuration string to be added.
+	 * @throws IllegalArgumentException
+	 *             Thrown if the given configurationString is either
+	 *             <code>null</code> or a zero-length string.
+	 * @throws IllegalStateException
+	 *             Thrown if not invoked in state
+	 *             <code>NodeState.CONFIGURING</code>.
 	 */
+	public abstract void addConfiguration(String configurationString);
+
+	/**
+	 * Returns the name of this node.
+	 * 
+	 * @return The name of this node.
+	 */
 	public abstract String getNodeName();
 
 	/**
-	 * Returns the node's state.
+	 * Returns the state of this node.
 	 * 
-	 * @return The node's state.
+	 * @return The state of this node.
 	 */
 	public abstract NodeState getNodeState();
 
 	/**
-	 * Determines the onion address for the previously added hidden service with
+	 * Determines the onion address for a previously added hidden service with
 	 * name <code>serviceName</code>. Requires that the node has been
 	 * started, i.e. is in state <code>NodeState.RUNNING</code>.
 	 * 
@@ -83,22 +99,29 @@
 	 *            Name of the hidden service that has been used before to add
 	 *            the hidden service. May neither be <code>null</code> or a
 	 *            zero-length string.
+	 * @param version
+	 *            Hidden service version; can be either 0, 1, or 2. Note that
+	 *            version 2 may not be implemented in the regular Tor sources!
 	 * @return The onion address string consisting of 16 base32 chars plus
-	 *         ".onion".
+	 *         ".onion" for hidden service versions 0 and 1 or 16 base32 chars
+	 *         plus "." plus 24 base32 chars plus ".onion" for hidden service
+	 *         version 2.
 	 * @throws IllegalArgumentException
 	 *             Thrown if <code>null</code> or a zero-length string is
 	 *             passed as parameter.
 	 * @throws TorProcessException
 	 *             Thrown if either there does not exist a hidden service with
-	 *             the given <code>serviceName</code> as directory or if the
+	 *             the given <code>serviceName</code> as directory, if the
+	 *             given <code>version</code> is invalid, or if the
 	 *             <code>hostname</code> file could not be read.
 	 */
-	public abstract String getOnionAddress(String serviceName)
+	public abstract String getOnionAddress(String serviceName, int version)
 			throws TorProcessException;
 
 	/**
 	 * Sends a HUP command to the process via its control port to restart it;
-	 * can only be done if node has already been started!
+	 * can only be done if the node has already been started, i.e. is in state
+	 * <code>NodeState.RUNNING</code>!
 	 * 
 	 * @throws TorProcessException
 	 *             Thrown if an I/O problem occurs while sending the HUP signal.
@@ -108,13 +131,14 @@
 	public abstract void hup() throws TorProcessException;
 
 	/**
-	 * Shuts down Tor process corresponding to this node immediately. This is
-	 * done by sending the <code>SHUTDOWN</code> signal twice, so that nodes
-	 * extending ProxyNode and have opened their OR port shutdown immediately,
-	 * too.
+	 * Shuts down the Tor process corresponding to this node immediately. This
+	 * is done by sending the <code>SHUTDOWN</code> signal twice, so that
+	 * those nodes extending <code>ProxyNode</code> which have opened their OR
+	 * port shutdown immediately, too.
 	 * 
 	 * @throws IllegalStateException
-	 *             Thrown if node is not in state <code>NodeState.RUNNING</code>.
+	 *             Thrown if this node is not in state
+	 *             <code>NodeState.RUNNING</code>.
 	 * @throws TorProcessException
 	 *             Thrown if an I/O problem occurs while sending the
 	 *             <code>SHUTDOWN</code> signal.
@@ -125,8 +149,8 @@
 	 * Starts the Tor process for this node and connects to the control port as
 	 * soon as it is opened. <b>In order for this method to succeed it is
 	 * absolutely necessary, that logging on the console is not changed in the
-	 * node's configuration to a higher level than NOTICE, because the output is
-	 * parsed to see when the control port is opened.</b>
+	 * configuration of this node to a higher level than NOTICE, because the
+	 * output is parsed to see when the control port is opened.</b>
 	 * 
 	 * @param maximumTimeToWaitInMillis
 	 *            Maximum time in millis we will wait for the Tor process to be
@@ -150,15 +174,29 @@
 			throws TorProcessException;
 
 	/**
-	 * Writes the node's configuration to the <code>torrc</code> file in the
-	 * node's working directory and changes the state to
+	 * Writes the configuration of this node to the <code>torrc</code> file in
+	 * its working directory and changes the state to
 	 * <code>NodeState.CONFIGURATION_WRITTEN</code>.
 	 * 
 	 * @throws IllegalStateException
 	 *             Thrown if not invoked in state
 	 *             <code>NodeState.CONFIGURING</code>.
 	 * @throws TorProcessException
-	 *             Thrown if the configuration file cannot be written to disk.
+	 *             Thrown if the configuration file <code>torrc</code> cannot
+	 *             be written to disk.
 	 */
 	public abstract void writeConfiguration() throws TorProcessException;
+
+	/**
+	 * Copies all locally stored descriptors of this node to the data directory
+	 * of the given <code>node</code>. Note that this method only makes sense
+	 * when used with a modified Tor implementation!
+	 * 
+	 * @param otherNode
+	 *            Node to which data directory the .rsd files shall be copied.
+	 * @throws TorProcessException
+	 *             Thrown if copying files does not succeed.
+	 */
+	public abstract void copyDescriptorTo(ProxyNode otherNode)
+			throws TorProcessException;
 }

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/RouterNode.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/RouterNode.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/RouterNode.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -1,11 +1,11 @@
 package de.uniba.wiai.lspi.puppetor;
 
 /**
- * A RouterNode represents a Tor process that is configured to both, relay
- * traffic from a local application to the Tor network and to route traffic on
- * behalf of remote applications. It inherits most of its configuration and
- * behavior from its superclass ProxyNode and adds some router-specific
- * configurations and behavior.
+ * A <code>RouterNode</code> represents a Tor process that is configured to
+ * both, relay traffic from a local application to the Tor network and to route
+ * traffic on behalf of remote applications. It inherits most of its
+ * configuration and behavior from its superclass <code>ProxyNode</code> and
+ * adds some router-specific configurations and behavior.
  * 
  * @author kloesing
  */
@@ -13,10 +13,11 @@
 
 	/**
 	 * <p>
-	 * Determines the directory node's fingerprint. If the Tor process has not
-	 * been started before, it is started to determine the node's fingerprint.
-	 * This is done using a temporary configuration file and with the
-	 * command-line option <code>--list-fingerprint</code>. Tor then
+	 * Determines the directory fingerprint of this node. If the Tor process has
+	 * not been started before, it is started and immediately stopped
+	 * afterwards, so that the Tor process creates a new onion key pair and
+	 * fingerprint for it. This is done using a temporary configuration file and
+	 * with the command-line option <code>--list-fingerprint</code>. Tor then
 	 * generates a new onion key and writes its fingerprint to the
 	 * <code>fingerprint</code> file in its working directory, but does not
 	 * start routing traffic.
@@ -43,7 +44,7 @@
 	 * before specifying directory servers for this node.
 	 * </p>
 	 * 
-	 * @return The content of the node's fingerprint file.
+	 * @return The content of the fingerprint file of this node.
 	 * @throws TorProcessException
 	 *             Thrown if either the temporary <code>torrc</code>
 	 *             configuration file cannot be written, the Tor process cannot

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ServerApplication.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ServerApplication.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/ServerApplication.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -11,11 +11,21 @@
 public interface ServerApplication extends EventSource {
 
 	/**
-	 * Starts listening for incoming <code>HTTP GET</code> requests by
+	 * Starts listening for incoming <code>HTTP GET</code> requests from
 	 * clients. Any incoming request is answered by an empty
-	 * <code>HTTP OK</code> reply.
+	 * <code>HTTP OK</code> reply. This method may only be invoked once!
+	 * 
+	 * @throws IllegalStateException
+	 *             Thrown if <code>listen</code> has already been invoked
+	 *             before.
 	 */
 	public abstract void listen();
 
-	// TODO we need some way to interrupt listening for requests
+	/**
+	 * Stops listening for requests.
+	 * 
+	 * @throws IllegalStateException
+	 *             Thrown if <code>listen</code> has not been invoked before.
+	 */
+	public abstract void stopListening();
 }

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/TorProcessException.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/TorProcessException.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/TorProcessException.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -5,9 +5,10 @@
  * exceptions that occur when interacting with the JVM-external Tor processes or
  * with the local file system. Any occurence of this exception denotes either a
  * configuration problem that can only be solved outside of the JVM, or an
- * unexpected problem. In contrast to this, all kinds of programming errors of a
- * test application (invoking a method with wrong parameter values, in wrong
- * state, etc.) will instead cause runtime exceptions from the Java API.
+ * unexpected problem. In contrast to this, all kinds of programming errors of
+ * an application using this API (invoking a method with wrong parameter values,
+ * in wrong state, etc.) will instead cause appropriate runtime exceptions from
+ * the Java API.
  * 
  * @author kloesing
  */
@@ -15,15 +16,16 @@
 public class TorProcessException extends Exception {
 
 	/**
-	 * Creates a TorProcessException without a detail message or cause.
+	 * Creates a <code>TorProcessException</code> without detail message or
+	 * cause.
 	 */
 	public TorProcessException() {
 		super();
 	}
 
 	/**
-	 * Creates a TorProcessException with the given detail <code>message</code>
-	 * and <code>cause</code>.
+	 * Creates a <code>TorProcessException</code> with the given detail
+	 * <code>message</code> and <code>cause</code>.
 	 * 
 	 * @param message
 	 *            The detail message of this exception.
@@ -35,8 +37,8 @@
 	}
 
 	/**
-	 * Creates a TorProcessException with the given detail <code>message</code>,
-	 * but without a cause.
+	 * Creates a <code>TorProcessException</code> with the given detail
+	 * <code>message</code>, but without a <code>cause</code>.
 	 * 
 	 * @param message
 	 *            The detail message of this exception.
@@ -46,8 +48,8 @@
 	}
 
 	/**
-	 * Creates a TorProcessException with the given <code>cause</code>, but
-	 * without a detail message.
+	 * Creates a <code>TorProcessException</code> with the given
+	 * <code>cause</code>, but without a detail message.
 	 * 
 	 * @param cause
 	 *            The cause for this exception.

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AccessingPublicWebServerOverTor.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AccessingPublicWebServerOverTor.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AccessingPublicWebServerOverTor.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -9,8 +9,8 @@
 import de.uniba.wiai.lspi.puppetor.TorProcessException;
 
 /**
- * Example for accessing a public Web server (www.google.com) over Tor to
- * measure access times.
+ * Example for accessing a public Web server (here: <code>www.google.com</code>)
+ * over Tor to measure access times.
  * 
  * @author kloesing
  */
@@ -20,16 +20,15 @@
 	 * Sets up and runs the test.
 	 * 
 	 * @param args
-	 *            Command-line arguments are ignored.
-	 * 
+	 *            Command-line arguments (ignored).
 	 * @throws TorProcessException
 	 *             Thrown if there is a problem with the JVM-external Tor
 	 *             processes that we cannot handle.
 	 */
 	public static void main(String[] args) throws TorProcessException {
 
-		// though we only need one proxy, we always need to create a network
-		// to initialize a test case
+		// though we only need a single proxy, we always need to create a
+		// network to initialize a test case.
 		Network network = NetworkFactory.createNetwork("example1");
 
 		// create a single proxy node with name "proxy", control port 7001,
@@ -57,7 +56,7 @@
 
 		// create client application
 		ClientApplication client = network.createClient("client",
-				"www.google.de", 80, 7002);
+				"www.google.com", 80, 7002);
 
 		// create event listener to listen for client application events
 		EventListener clientEventListener = new EventListener() {
@@ -92,9 +91,20 @@
 		manager.waitForAnyOccurence(client,
 				Event.APPLICATION_REQUESTS_PERFORMED);
 
+		// wait a second before shutting down the proxy
+		try {
+			Thread.sleep(1000);
+		} catch (InterruptedException e) {
+		}
+
 		// shut down proxy
 		network.shutdownNodes();
 
-		System.out.println("Exiting...");
+		// wait another second before exiting the application
+		try {
+			Thread.sleep(1000);
+		} catch (InterruptedException e) {
+		}
+
 	}
 }

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingAndAccessingHiddenServiceOverPrivateTorNetwork.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingAndAccessingHiddenServiceOverPrivateTorNetwork.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingAndAccessingHiddenServiceOverPrivateTorNetwork.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -22,8 +22,7 @@
 	 * Sets up and runs the test.
 	 * 
 	 * @param args
-	 *            Command-line arguments are ignored.
-	 * 
+	 *            Command-line arguments (ignored).
 	 * @throws TorProcessException
 	 *             Thrown if there is a problem with the JVM-external Tor
 	 *             processes that we cannot handle.
@@ -45,14 +44,15 @@
 		RouterNode router1 = network.createRouter("router1", 7021, 7022, 7023,
 				7024);
 		network.createRouter("router2", 7031, 7032, 7033, 7034);
-		network.createRouter("router3", 7041, 7042, 7043, 7044);
+		network.createRouter("router3", 7041, 7042, 7043,
+				7044);
 
 		// create two directory nodes with parameters (router name, control
 		// port, SOCKS port, OR port, dir port)
 		network.createDirectory("dir1", 7051, 7052, 7053, 7054);
 		network.createDirectory("dir2", 7061, 7062, 7063, 7064);
 
-		// add hidden service to the configuration of proxy1
+		// add hidden service
 		router1.addHiddenService("hidServ", 7025, 80);
 
 		// configure nodes of this network to be part of a private network
@@ -62,93 +62,72 @@
 		network.writeConfigurations();
 
 		// start proxy node and wait until it has opened a circuit with a
-		// timeout of 5 seconds
-		if (!network.startNodes(5000)) {
+		// timeout of 15 seconds
+		if (!network.startNodes(15000)) {
 
 			// failed to start the proxy
 			System.out.println("Failed to start nodes!");
 			return;
 		}
+		System.out.println("Successfully started nodes!");
 
-		// hup until proxy has built circuits (8 retries, 10 seconds timeout
+		// hup until proxy has built circuits (10 retries, 10 seconds timeout
 		// each)
-		if (!network.hupUntilUp(8, 10000)) {
+		if (!network.hupUntilUp(10, 10000)) {
 
 			// failed to build circuits
 			System.out.println("Failed to build circuits!");
 			return;
 		}
+		System.out.println("Successfully built circuits!");
 
 		// obtain reference to event manager to be able to respond to events
 		EventManager manager = network.getEventManager();
 
 		// wait for 3 minutes that the proxy has published its first RSD
+
 		if (!manager.waitForAnyOccurence(router1, Event.NODE_RSD_PUBLISHED,
 				3L * 60L * 1000L)) {
-
 			// failed to publish an RSD
 			System.out.println("Failed to publish an RSD!");
 			return;
 		}
+		System.out.println("All RSDs published!");
 
 		// determine onion address for hidden service
-		String onionAddress = router1.getOnionAddress("hidServ");
+		String onionAddress = router1.getOnionAddress("hidServ", 1);
 
 		// create server application
 		ServerApplication server = network.createServer("server", 7025);
 
+		// start server
+		server.listen();
+		System.out.println("Started server");
+
 		// create client application
 		ClientApplication client = network.createClient("client", onionAddress,
 				80, 7042);
 
-		// create event listener to listen for client and server application
-		// events
+		// register event listener
 		EventListener clientAndServerEventListener = new EventListener() {
 
-			private long requestReceivedAtServer;
-
-			// remember time when request was sent and when it was received
-			private long requestSentFromClient;
-
 			public void handleEvent(Event event) {
-				switch (event) {
-				case APPLICATION_SENDING_REQUEST:
-					requestSentFromClient = System.currentTimeMillis();
-					break;
-				case APPLICATION_REQUEST_RECEIVED:
-					requestReceivedAtServer = System.currentTimeMillis();
-					System.out.println("Request took "
-							+ (requestReceivedAtServer - requestSentFromClient)
-							+ " millis from client to server!");
-					break;
-				case APPLICATION_REPLY_RECEIVED:
-					System.out
-							.println("Request took "
-									+ (System.currentTimeMillis() - requestSentFromClient)
-									+ " millis for the rount-trip and "
-									+ (System.currentTimeMillis() - requestReceivedAtServer)
-									+ " millis from server to client!");
-				}
+				System.out.println("Handling event: " + event);
+
 			}
 		};
-
-		// register event handler for client and server application events
 		manager.addEventListener(client, clientAndServerEventListener);
 		manager.addEventListener(server, clientAndServerEventListener);
 
-		// start server
-		server.listen();
-
 		// perform at most five request with a timeout of 45 seconds each
 		client.performRequest(5, 45000, true);
 
-		// block this thread as long as client requests are running
+		// wait for request to be performed
 		manager.waitForAnyOccurence(client,
 				Event.APPLICATION_REQUESTS_PERFORMED);
 
-		// shut down proxy
+		// shut down nodes
 		network.shutdownNodes();
 
-		System.out.println("Exiting...");
 	}
 }

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingAndAccessingHiddenServiceOverPublicTorNetwork.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingAndAccessingHiddenServiceOverPublicTorNetwork.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingAndAccessingHiddenServiceOverPublicTorNetwork.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -22,8 +22,7 @@
 	 * Sets up and runs the test.
 	 * 
 	 * @param args
-	 *            Command-line arguments are ignored.
-	 * 
+	 *            Command-line arguments (ignored).
 	 * @throws TorProcessException
 	 *             Thrown if there is a problem with the JVM-external Tor
 	 *             processes that we cannot handle.
@@ -78,7 +77,7 @@
 		ServerApplication server = network.createServer("server", 7005);
 
 		// determine onion address for hidden service
-		String onionAddress = proxy1.getOnionAddress("hidServ");
+		String onionAddress = proxy1.getOnionAddress("hidServ", 1);
 
 		// create client application
 		ClientApplication client = network.createClient("client", onionAddress,

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingHiddenServiceToPublicTorNetwork.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingHiddenServiceToPublicTorNetwork.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/AdvertisingHiddenServiceToPublicTorNetwork.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -20,8 +20,7 @@
 	 * Sets up and runs the test.
 	 * 
 	 * @param args
-	 *            Command-line arguments are ignored.
-	 * 
+	 *            Command-line arguments (ignored).
 	 * @throws TorProcessException
 	 *             Thrown if there is a problem with the JVM-external Tor
 	 *             processes that we cannot handle.
@@ -87,12 +86,12 @@
 			return;
 		}
 
-		// let it run for 5 minutes and observe when RSDs are published...
+		// let it run for 2 minutes and observe when RSDs are published...
 		System.out
-				.println("Waiting for 5 minutes and observing RSD publications...");
+				.println("Waiting for 2 minutes and observing RSD publications...");
 
 		try {
-			Thread.sleep(5L * 60L * 1000L);
+			Thread.sleep(2L * 60L * 1000L);
 		} catch (InterruptedException e) {
 			// do nothing
 		}

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ClientApplicationImpl.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ClientApplicationImpl.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ClientApplicationImpl.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -1,8 +1,3 @@
-/*
- * NOTICE: This file is still work in progress. As you can see the Java
- * documentation is written partly in German and in English and logging and
- * documentation still need some work. Sorry for any inconvenience!  
- */
 package de.uniba.wiai.lspi.puppetor.impl;
 
 import java.io.BufferedReader;
@@ -21,182 +16,51 @@
 import de.uniba.wiai.lspi.puppetor.Event;
 
 /**
- * Implementation of ClientApplication.
+ * Implementation of <code>ClientApplication</code>.
  * 
  * @author kloesing
  */
 public class ClientApplicationImpl implements ClientApplication {
 
 	/**
-	 * Thread that performs the requests in the background
+	 * Internal thread class that is used to perform requests.
 	 */
-	private RequestThread clientThread;
+	private class RequestThread extends Thread {
 
-	/**
-	 * Logger for this client
-	 */
-	private Logger logger;
+		/**
+		 * Flag to remember whether requests are performed at the moment (<code>true</code>),
+		 * or have been stopped (<code>false</code>).
+		 */
+		private boolean connected;
 
-	/**
-	 * Target address for requests; can be either a server address or an onion
-	 * address.
-	 */
-	private String targetAddress;
+		/**
+		 * Number of retries to be performed.
+		 */
+		private int retries;
 
-	/**
-	 * Target port for requests; can be either a server port or a virtual port
-	 * of a hidden service.
-	 */
-	private int targetPort;
+		/**
+		 * Flag that determines whether requests shall be stopped after the
+		 * first successful reply (<code>true</code>), or not (<code>false</code>).
+		 */
+		private boolean stopOnSuccess;
 
-	/**
-	 * SOCKS port of the local Tor node.
-	 */
-	private int socksPort;
-
-	/**
-	 * 
-	 */
-	private EventManagerImpl eventManager;
-
-	/**
-	 * 
-	 */
-	private String clientApplicationName;
-
-	/**
-	 * (logging finished)
-	 * 
-	 * erzeugt neue client app innerhalb der jvm, started aber noch keine
-	 * requests.
-	 * 
-	 * @param network
-	 * 
-	 * @param clientApplicationName
-	 *            für logging
-	 * @param targetAddress
-	 *            Target address for requests; can be either a server address or
-	 *            an onion address.
-	 * @param targetPort
-	 *            Target port for requests; can be either a server port or a
-	 *            virtual port of a hidden service.
-	 * @param socksPort
-	 *            SOCKS port of the local Tor node.
-	 */
-	ClientApplicationImpl(NetworkImpl network, String clientApplicationName,
-			String targetAddress, int targetPort, int socksPort) {
-
-		// TODO make sure that name is loggable!!
-
-		// create logger
-		this.logger = Logger.getLogger("application." + clientApplicationName);
-
-		// log entering
-		this.logger.entering(this.getClass().getName(),
-				"ClientApplicationImpl", new Object[] { clientApplicationName,
-						targetAddress, targetPort, socksPort });
-
-		// check parameters
-		if (clientApplicationName == null
-				|| clientApplicationName.length() == 0 || targetAddress == null
-				|| targetAddress.length() == 0 || targetPort < 0
-				|| targetPort > 65535 || socksPort < 0 || socksPort > 65535) {
-
-			IllegalArgumentException e = new IllegalArgumentException("bla");
-			this.logger.throwing(this.getClass().getName(),
-					"ClientApplicationImpl", e);
-			throw e;
-		}
-
-		// remember parameters
-		this.clientApplicationName = clientApplicationName;
-		this.targetAddress = targetAddress;
-		this.targetPort = targetPort;
-		this.socksPort = socksPort;
-
-		// obtain reference on event manager
-		this.eventManager = network.getEventManagerImpl();
-
-		// log exiting
-		this.logger.exiting(this.getClass().getName(), "ClientApplicationImpl");
-	}
-
-	/**
-	 * bricht alle laufenden requests ab
-	 * 
-	 */
-	public void stopRequest() {
-
-		// log entering
-		this.logger.entering(this.getClass().getName(), "stopRequest");
-
-		// check if a request is running
-		if (this.clientThread == null) {
-			throw new IllegalStateException("No request has been started!");
-		}
-
-		// log this event
-		this.logger.log(Level.FINE, "Shutting down client");
-
-		// interrupt thread
-		this.clientThread.stopRequest();
-
-		// log exiting
-		this.logger.exiting(this.getClass().getName(), "stopRequest");
-	}
-
-	/**
-	 * (logging done)
-	 * 
-	 * startet einen oder mehrere aufeinander folgende aufrufe an die im
-	 * konstruktor übergebene adresse und port.
-	 */
-	public void performRequest(int retries, long timeoutForEachRetry,
-			boolean stopOnSuccess) {
-
-		// log entering
-		this.logger.entering(this.getClass().getName(), "performRequest",
-				new Object[] { retries, timeoutForEachRetry, stopOnSuccess });
-
-		// check parameters
-		if (retries <= 0 || timeoutForEachRetry < 0) {
-			throw new IllegalArgumentException();
-		}
-
-		// check if we already have started a request (TODO change this to allow
-		// multiple requests in parallel? would be possible)
-		if (this.clientThread != null) {
-			throw new IllegalStateException(
-					"Another request has already been started!");
-		}
-
-		// create a thread that performs requests in the background
-		this.clientThread = new RequestThread(retries, timeoutForEachRetry,
-				stopOnSuccess);
-		this.clientThread.setName("Request Thread");
-		this.clientThread.setDaemon(true);
-		this.clientThread.start();
-
-		// log exiting
-		this.logger.exiting(this.getClass().getName(), "performRequest");
-	}
-
-	/**
-	 * (logging done)
-	 * 
-	 * @author kloesing
-	 * 
-	 */
-	private class RequestThread extends Thread {
-
-		private int retries;
-
+		/**
+		 * Timeout in milliseconds for each retry.
+		 */
 		private long timeoutForEachRetry;
 
-		private boolean connected;
-
-		private boolean stopOnSuccess;
-
+		/**
+		 * Creates a new thread, but does not start performing requests, yet.
+		 * 
+		 * @param retries
+		 *            Number of retries to be performed.
+		 * @param timeoutForEachRetry
+		 *            Timeout in milliseconds for each retry.
+		 * @param stopOnSuccess
+		 *            Flag that determines whether requests shall be stopped
+		 *            after the first successful reply (<code>true</code>),
+		 *            or not (<code>false</code>).
+		 */
 		RequestThread(int retries, long timeoutForEachRetry,
 				boolean stopOnSuccess) {
 
@@ -206,6 +70,13 @@
 							new Object[] { retries, timeoutForEachRetry,
 									stopOnSuccess });
 
+			// check parameters
+			if (retries < 0 || timeoutForEachRetry < 0) {
+				IllegalArgumentException e = new IllegalArgumentException();
+				logger.throwing(this.getClass().getName(), "RequestThread", e);
+				throw e;
+			}
+
 			// remember parameters
 			this.retries = retries;
 			this.timeoutForEachRetry = timeoutForEachRetry;
@@ -219,25 +90,8 @@
 		}
 
 		/**
-		 * stoppt diesen request egal wo er gerade steht
-		 * 
+		 * Perform one or more requests.
 		 */
-		public void stopRequest() {
-
-			// log entering
-			logger.entering(this.getClass().getName(), "stopRequest");
-
-			// change connected state to false and interrupt thread
-			this.connected = false;
-			this.interrupt();
-
-			// log exiting
-			logger.exiting(this.getClass().getName(), "stopRequest");
-		}
-
-		/**
-		 * (logging done)
-		 */
 		@Override
 		public void run() {
 
@@ -251,12 +105,12 @@
 						socksPort);
 				Proxy p = new Proxy(Type.SOCKS, isa);
 
-				// create target address for socket -- don't resolve the target address
-				// to an IP address!
-				InetSocketAddress hs = InetSocketAddress.createUnresolved(targetAddress,
-						targetPort);
+				// create target address for socket -- don't resolve the target
+				// name to an IP address!
+				InetSocketAddress hs = InetSocketAddress.createUnresolved(
+						targetName, targetPort);
 
-				// start loop
+				// start retry loop
 				for (int i = 0; connected && i < retries; i++) {
 
 					// log this try
@@ -331,7 +185,7 @@
 
 						// wait for the rest of the timeout
 						long timeOfTimeoutLeft = timeBeforeConnectionAttempt
-								+ timeoutForEachRetry
+								+ this.timeoutForEachRetry
 								- System.currentTimeMillis();
 						if (timeOfTimeoutLeft > 0) {
 							try {
@@ -379,13 +233,189 @@
 				logger.exiting(this.getClass().getName(), "run");
 			}
 		}
+
+		/**
+		 * Immediately stops this and all possibly subsequent requests.
+		 */
+		public void stopRequest() {
+
+			// log entering
+			logger.entering(this.getClass().getName(), "stopRequest");
+
+			// change connected state to false and interrupt thread
+			this.connected = false;
+			this.interrupt();
+
+			// log exiting
+			logger.exiting(this.getClass().getName(), "stopRequest");
+		}
 	}
 
+	/**
+	 * Name of this client application that is used as logger name of this node.
+	 */
+	private String clientApplicationName;
+
+	/**
+	 * Thread that performs the requests in the background.
+	 */
+	private RequestThread clientThread;
+
+	/**
+	 * Event manager to which all events concerning this client application are
+	 * notified.
+	 */
+	private EventManagerImpl eventManager;
+
+	/**
+	 * Logger for this client.
+	 */
+	private Logger logger;
+
+	/**
+	 * SOCKS port of the local Tor node to which requests are sent.
+	 */
+	private int socksPort;
+
+	/**
+	 * Target name for the requests sent by this client; can be either a server
+	 * name/address or an onion address.
+	 */
+	private String targetName;
+
+	/**
+	 * Target port for the requests sent by this client; can be either a server
+	 * port or a virtual port of a hidden service.
+	 */
+	private int targetPort;
+
+	/**
+	 * Creates a new HTTP client within this JVM, but does not start sending
+	 * requests.
+	 * 
+	 * @param network
+	 *            Network to which this HTTP client belongs; at the moment this
+	 *            is only used to determine the event manager instance.
+	 * @param clientApplicationName
+	 *            Name of this client that is used as part of the logger name.
+	 * @param targetName
+	 *            Target name for requests; can be either a server name/address
+	 *            or an onion address.
+	 * @param targetPort
+	 *            Target port for requests; can be either a server port or a
+	 *            virtual port of a hidden service.
+	 * @param socksPort
+	 *            SOCKS port of the local Tor node.
+	 * @throws IllegalArgumentException
+	 *             If at least one of the parameters is <code>null</code> or has an invalid
+	 *             value.
+	 */
+	ClientApplicationImpl(NetworkImpl network, String clientApplicationName,
+			String targetName, int targetPort, int socksPort) {
+
+		// check if clientApplicationName can be used as logger name
+		if (clientApplicationName == null
+				|| clientApplicationName.length() == 0) {
+			throw new IllegalArgumentException(
+					"Invalid clientApplicationName: " + clientApplicationName);
+		}
+
+		// create logger
+		this.logger = Logger.getLogger("application." + clientApplicationName);
+
+		// log entering
+		this.logger.entering(this.getClass().getName(),
+				"ClientApplicationImpl", new Object[] { network,
+						clientApplicationName, targetName, targetPort,
+						socksPort });
+
+		// check parameters
+		if (network == null || targetName == null || targetName.length() == 0
+				|| targetPort < 0 || targetPort > 65535 || socksPort < 0
+				|| socksPort > 65535) {
+			IllegalArgumentException e = new IllegalArgumentException();
+			this.logger.throwing(this.getClass().getName(),
+					"ClientApplicationImpl", e);
+			throw e;
+		}
+
+		// remember parameters
+		this.clientApplicationName = clientApplicationName;
+		this.targetName = targetName;
+		this.targetPort = targetPort;
+		this.socksPort = socksPort;
+
+		// obtain and store reference on event manager
+		this.eventManager = network.getEventManagerImpl();
+
+		// log exiting
+		this.logger.exiting(this.getClass().getName(), "ClientApplicationImpl");
+	}
+
+	public synchronized void performRequest(int retries,
+			long timeoutForEachRetry, boolean stopOnSuccess) {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "performRequest",
+				new Object[] { retries, timeoutForEachRetry, stopOnSuccess });
+
+		// check parameters
+		if (retries <= 0 || timeoutForEachRetry < 0) {
+			IllegalArgumentException e = new IllegalArgumentException();
+			this.logger
+					.throwing(this.getClass().getName(), "performRequest", e);
+			throw e;
+		}
+
+		// check if we already have started a request (TODO change this to allow
+		// multiple requests in parallel? would be possible)
+		if (this.clientThread != null) {
+			IllegalStateException e = new IllegalStateException(
+					"Another request has already been started!");
+			this.logger
+					.throwing(this.getClass().getName(), "performRequest", e);
+			throw e;
+		}
+
+		// create a thread that performs requests in the background
+		this.clientThread = new RequestThread(retries, timeoutForEachRetry,
+				stopOnSuccess);
+		this.clientThread.setName("Request Thread");
+		this.clientThread.setDaemon(true);
+		this.clientThread.start();
+
+		// log exiting
+		this.logger.exiting(this.getClass().getName(), "performRequest");
+	}
+
+	public synchronized void stopRequest() {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "stopRequest");
+
+		// check if a request is running
+		if (this.clientThread == null) {
+			IllegalStateException e = new IllegalStateException("Cannot stop "
+					+ "request, because no request has been started!");
+			this.logger.throwing(this.getClass().getName(), "stopRequest", e);
+			throw e;
+		}
+
+		// log this event
+		this.logger.log(Level.FINE, "Shutting down client");
+
+		// interrupt thread
+		this.clientThread.stopRequest();
+
+		// log exiting
+		this.logger.exiting(this.getClass().getName(), "stopRequest");
+	}
+
 	@Override
 	public String toString() {
 		return this.getClass().getSimpleName() + ": clientApplicationName=\""
 				+ this.clientApplicationName + "\", targetAddress=\""
-				+ this.targetAddress + "\", targetPort=" + this.targetPort
+				+ this.targetName + "\", targetPort=" + this.targetPort
 				+ ", socksPort=" + this.socksPort;
 	}
 }

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/DirectoryNodeImpl.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/DirectoryNodeImpl.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/DirectoryNodeImpl.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -1,8 +1,3 @@
-/*
- * NOTICE: This file is still work in progress. As you can see the Java
- * documentation is written partly in German and in English and logging and
- * documentation still need some work. Sorry for any inconvenience!  
- */
 package de.uniba.wiai.lspi.puppetor.impl;
 
 import java.io.BufferedWriter;
@@ -16,19 +11,59 @@
 import de.uniba.wiai.lspi.puppetor.DirectoryNode;
 import de.uniba.wiai.lspi.puppetor.TorProcessException;
 
+/**
+ * Implementation of <code>DirectoryNode</code>.
+ * 
+ * @author karsten
+ */
 public class DirectoryNodeImpl extends RouterNodeImpl implements DirectoryNode {
+
 	/**
-	 * Initializes this Tor node, but does not start it, yet.
+	 * Creates a <code>DirectoryNodeImpl</code> and adds it to the given
+	 * <code>network</code>, but does not yet write its configuration to disk
+	 * or start the corresponding Tor process.
+	 * 
+	 * @param network
+	 *            Network configuration to which this node belongs.
+	 * @param nodeName
+	 *            The name of the new node which may only consist of between 1
+	 *            and 19 alpha-numeric characters.
+	 * @param controlPort
+	 *            Port on which the Tor node will be listening for us as its
+	 *            controller. May not be negative or greater than 65535.
+	 * @param socksPort
+	 *            Port on which the Tor node will be listening for SOCKS
+	 *            connection requests. May not be negative or greater than
+	 *            65535.
+	 * @param orPort
+	 *            Port on which the Tor node will be listening for onion
+	 *            requests by other Tor nodes. May not be negative or greater
+	 *            than 65535.
+	 * @param dirPort
+	 *            Port on which the Tor node will be listening for directory
+	 *            requests from other Tor nodes. May not be negative or greater
+	 *            than 65535.
+	 * @throws IllegalArgumentException
+	 *             If at least one of the parameters is <code>null</code> or
+	 *             has an invalid value.
 	 */
-	public DirectoryNodeImpl(NetworkImpl network, String nodeName,
-			int controlPort, int socksPort, int orPort, int dirPort) {
+	DirectoryNodeImpl(NetworkImpl network, String nodeName, int controlPort,
+			int socksPort, int orPort, int dirPort) {
+
+		// create superclass instance; parameter checking is done in super
+		// constructor
 		super(network, nodeName, controlPort, socksPort, orPort, dirPort);
 
+		// log entering
+		this.logger.entering(this.getClass().getName(), "DirectoryNodeImpl",
+				new Object[] { network, nodeName, controlPort, socksPort,
+						orPort, dirPort });
+
 		// configure this node as an authoritative directory
 		this.configuration.add("AuthoritativeDirectory 1");
 
 		// TODO make this a little bit more configurable---same as to
-		// location of tor.exe?
+		// location of tor executable?
 		this.configuration
 				.add("RecommendedVersions 0.1.2.12-rc,0.1.2.7-alpha-dev,0.2.0.0-alpha-dev");
 
@@ -36,19 +71,61 @@
 
 		this.configuration.add("NamingAuthoritativeDirectory 1");
 
-		this.configuration.add("V2AuthoritativeDirectory 1");
+		// TODO this requires version 0.2.x
+		//this.configuration.add("V2AuthoritativeDirectory 1");
 		this.configuration.add("V1AuthoritativeDirectory 1");
 
 		// TODO this only works since Tor 0.1.2.x!!!
 		this.configuration.add("HSAuthoritativeDir 1");
 
+		// TODO only in v0.2.x
+		//this.configuration.add("HSAuthorityRecordStats 1");
+
+		// log exiting
+		this.logger.exiting(this.getClass().getName(), "DirectoryNodeImpl");
 	}
 
-	public void writeApprovedRouters(Set<String> approvedRouters)
+	public synchronized String determineDirServerString()
 			throws TorProcessException {
-		
-		// check param!
-		
+
+		// log entering
+		this.logger.entering(this.getClass().getName(),
+				"determineDirServerString");
+
+		// determine fingerprint
+		String fingerprint = determineFingerprint();
+
+		// cut off router nickname
+		fingerprint = fingerprint.substring(fingerprint.indexOf(" ") + 1);
+
+		// put everything together
+		String dirServerString = "DirServer " + this.nodeName + " hs orport="
+				+ this.orPort + " " + localIpAddress + ":" + this.dirPort + " "
+				+ fingerprint;
+
+		// log exiting and return dir server string
+		this.logger.exiting(this.getClass().getName(),
+				"determineDirServerString", dirServerString);
+		return dirServerString;
+	}
+
+	public synchronized void writeApprovedRouters(Set<String> approvedRouters)
+			throws TorProcessException {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "writeApprovedRouters",
+				approvedRouters);
+
+		// check parameter
+		if (approvedRouters == null) {
+			IllegalArgumentException e = new IllegalArgumentException();
+			this.logger.throwing(this.getClass().getName(),
+					"writeApprovedRouters", e);
+			throw e;
+		}
+
+		// sort the given approved router strings alphabetically and store them
+		// to file
 		try {
 			File approvedRoutersFile = new File(this.workingDir
 					.getAbsolutePath()
@@ -62,22 +139,13 @@
 			}
 			bw.close();
 		} catch (IOException e) {
-			throw new TorProcessException(e);
+			TorProcessException ex = new TorProcessException(e);
+			this.logger.throwing(this.getClass().getName(),
+					"writeApprovedRouters", ex);
+			throw ex;
 		}
-	}
 
-	public synchronized String determineDirServerString()
-			throws TorProcessException {
-
-		// determine fingerprint
-		String fingerprint = determineFingerprint();
-
-		// cut off router nickname
-		fingerprint = fingerprint.substring(fingerprint.indexOf(" ") + 1);
-
-		// put together everything
-		String dirServerString = "DirServer " + this.nodeName
-				+ " hs " + localIpAddress + ":" + this.dirPort + " " + fingerprint;
-		return dirServerString;
+		// log exiting
+		this.logger.exiting(this.getClass().getName(), "writeApprovedRouters");
 	}
 }

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/EventManagerImpl.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/EventManagerImpl.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/EventManagerImpl.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -1,8 +1,3 @@
-/*
- * NOTICE: This file is still work in progress. As you can see the Java
- * documentation is written partly in German and in English and logging and
- * documentation still need some work. Sorry for any inconvenience!  
- */
 package de.uniba.wiai.lspi.puppetor.impl;
 
 import java.util.ArrayList;
@@ -19,23 +14,61 @@
 import de.uniba.wiai.lspi.puppetor.EventManager;
 import de.uniba.wiai.lspi.puppetor.EventSource;
 
+/**
+ * Implementation of <code>EventManager</code>.
+ */
 public class EventManagerImpl implements EventManager {
 
+	/**
+	 * Registered event handlers.
+	 */
+	private Map<EventSource, Set<EventListener>> eventHandlers;
+
+	/**
+	 * Logger for this <code>EventManagerImpl</code> instance which is called
+	 * "event." plus the name of the network.
+	 */
 	private Logger logger;
 
+	/**
+	 * Events observed so far.
+	 */
+	private Map<EventSource, List<Event>> observedEvents;
+
+	/**
+	 * Creates a new <code>EventManagerImpl</code> for the network with name
+	 * <code>networkName</code> and initializes it.
+	 * 
+	 * @param networkName
+	 *            Name of this event manager that is used as part of the logger
+	 *            name.
+	 * @throws IllegalArgumentException
+	 *             Thrown if the given <code>networkName</code> is either
+	 *             <code>null</code> or a zero-length string.
+	 */
 	EventManagerImpl(String networkName) {
-		
-//		 TODO make sure that name is loggable!!
-		
+
+		// check if networkName can be used as logger name
+		if (networkName == null || networkName.length() == 0) {
+			throw new IllegalArgumentException("Invalid networkName: "
+					+ networkName);
+		}
+
+		// create logger
 		this.logger = Logger.getLogger("event." + networkName);
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "EventManagerImpl",
+				networkName);
+
+		// create data structures
 		this.observedEvents = new HashMap<EventSource, List<Event>>();
 		this.eventHandlers = new HashMap<EventSource, Set<EventListener>>();
+
+		// log exiting
+		this.logger.exiting(this.getClass().getName(), "EventManagerImpl");
 	}
 
-	private Map<EventSource, List<Event>> observedEvents;
-
-	private Map<EventSource, Set<EventListener>> eventHandlers;
-
 	public synchronized List<Event> addEventListener(EventSource source,
 			EventListener listener) {
 
@@ -45,7 +78,10 @@
 
 		// check parameters
 		if (source == null || listener == null) {
-			throw new IllegalArgumentException();
+			IllegalArgumentException e = new IllegalArgumentException();
+			this.logger.throwing(this.getClass().getName(), "addEventListener",
+					e);
+			throw e;
 		}
 
 		// if necessary, create new event listener set for source
@@ -70,12 +106,15 @@
 	public synchronized List<Event> getEventHistory(EventSource source) {
 
 		// log entering
-		this.logger.entering(this.getClass().getName(), "getNodeEventHistory",
+		this.logger.entering(this.getClass().getName(), "getEventHistory",
 				source);
 
 		// check parameter
 		if (source == null) {
-			throw new IllegalArgumentException();
+			IllegalArgumentException e = new IllegalArgumentException();
+			this.logger.throwing(this.getClass().getName(), "getEventHistory",
+					e);
+			throw e;
 		}
 
 		// prepare result
@@ -88,10 +127,9 @@
 		}
 
 		// log exiting and return result
-		this.logger.exiting(this.getClass().getName(), "getNodeEventHistory",
+		this.logger.exiting(this.getClass().getName(), "getEventHistory",
 				result);
 		return result;
-
 	}
 
 	public synchronized boolean hasEventOccured(EventSource source, Event event) {
@@ -102,7 +140,10 @@
 
 		// check parameters
 		if (source == null || event == null) {
-			throw new IllegalArgumentException();
+			IllegalArgumentException e = new IllegalArgumentException();
+			this.logger.throwing(this.getClass().getName(), "hasEventOccured",
+					e);
+			throw e;
 		}
 
 		// determine result
@@ -115,6 +156,57 @@
 		return result;
 	}
 
+	/**
+	 * Stores the given <code>event</code> from <code>source</code> to the
+	 * event history and propagates its occurrence to all registered event
+	 * handlers.
+	 * 
+	 * @param source
+	 *            The source of the given event.
+	 * @param event
+	 *            The event type.
+	 */
+	synchronized void observeEvent(EventSource source, Event event) {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "observeEvent",
+				new Object[] { source, event });
+
+		this.logger.log(Level.FINE, "Observed event " + event + " from source "
+				+ source + "!");
+
+		// remember observed event
+		if (!this.observedEvents.containsKey(source)) {
+			this.observedEvents.put(source, new ArrayList<Event>());
+		}
+		this.observedEvents.get(source).add(event);
+
+		// notify waiting threads
+		notifyAll();
+
+		// inform event listeners
+		if (this.eventHandlers.containsKey(source)) {
+
+			// make a copy of the event handler set, because some event handlers
+			// might want to remove themselves from this set while handling the
+			// event
+
+			Set<EventListener> copyOfEventHandlers = new HashSet<EventListener>(
+					this.eventHandlers.get(source));
+
+			for (EventListener eventHandler : copyOfEventHandlers) {
+
+				this.logger.log(Level.FINE, "Informing event listener "
+						+ eventHandler + " about recently observed event "
+						+ event + " from source " + source + "!");
+				eventHandler.handleEvent(event);
+			}
+		}
+
+		// log exiting
+		this.logger.exiting(this.getClass().getName(), "observeEvent");
+	}
+
 	public synchronized void removeEventListener(EventListener eventListener) {
 
 		// log entering
@@ -123,7 +215,10 @@
 
 		// check parameters
 		if (eventListener == null) {
-			throw new IllegalArgumentException();
+			IllegalArgumentException e = new IllegalArgumentException();
+			this.logger.throwing(this.getClass().getName(),
+					"removeEventListener", e);
+			throw e;
 		}
 
 		// don't know to which source this listener has been added (may to more
@@ -146,7 +241,10 @@
 
 		// check parameters
 		if (source == null || event == null) {
-			throw new IllegalArgumentException();
+			IllegalArgumentException e = new IllegalArgumentException();
+			this.logger.throwing(this.getClass().getName(),
+					"waitForAnyOccurence", e);
+			throw e;
 		}
 
 		// invoke overloaded method with maximumTimeToWaitInMillis of -1L which
@@ -167,15 +265,16 @@
 
 		// check parameters
 		if (source == null || event == null) {
-			throw new IllegalArgumentException();
+			IllegalArgumentException e = new IllegalArgumentException();
+			this.logger.throwing(this.getClass().getName(),
+					"waitForAnyOccurence", e);
+			throw e;
 		}
 
 		// check if we have already observed the event
 		if (this.hasEventOccured(source, event)) {
-
 			this.logger.log(Level.FINE, "Waiting for any occurence of event "
 					+ event + " returned immediately!");
-
 			this.logger.exiting(this.getClass().getName(),
 					"waitForAnyOccurence", true);
 			return true;
@@ -189,7 +288,6 @@
 		this.logger.exiting(this.getClass().getName(), "waitForAnyOccurence",
 				result);
 		return result;
-
 	}
 
 	public synchronized void waitForNextOccurence(EventSource source,
@@ -201,7 +299,10 @@
 
 		// check parameters
 		if (source == null || event == null) {
-			throw new IllegalArgumentException();
+			IllegalArgumentException e = new IllegalArgumentException();
+			this.logger.throwing(this.getClass().getName(),
+					"waitForNextOccurence", e);
+			throw e;
 		}
 
 		// invoke overloaded method with maximumTimeToWaitInMillis of -1L which
@@ -210,7 +311,6 @@
 
 		// log exiting
 		this.logger.exiting(this.getClass().getName(), "waitForNextOccurence");
-
 	}
 
 	public synchronized boolean waitForNextOccurence(EventSource source,
@@ -222,7 +322,10 @@
 
 		// check parameters
 		if (source == null || event == null) {
-			throw new IllegalArgumentException();
+			IllegalArgumentException e = new IllegalArgumentException();
+			this.logger.throwing(this.getClass().getName(),
+					"waitForNextOccurence", e);
+			throw e;
 		}
 
 		// distinguish between negative waiting time (wait forever) and zero or
@@ -299,50 +402,4 @@
 		}
 	}
 
-	/**
-	 * wird lokal aufgerufen; speichert event in history und meldet es an alle
-	 * registrierten event handler weiter
-	 * 
-	 */
-	synchronized void observeEvent(EventSource source, Event event) {
-
-		// log entering
-		this.logger.entering(this.getClass().getName(), "observeEvent",
-				new Object[] { source, event });
-
-		this.logger.log(Level.FINE, "Observed event " + event + " from source "
-				+ source + "!");
-
-		// remember observed event
-		if (!this.observedEvents.containsKey(source)) {
-			this.observedEvents.put(source, new ArrayList<Event>());
-		}
-		this.observedEvents.get(source).add(event);
-
-		// notify waiting threads
-		notifyAll();
-
-		// inform event listeners
-		if (this.eventHandlers.containsKey(source)) {
-
-			// make a copy of the event handler set, because some event handlers
-			// might want to remove itself from this set while handling the
-			// event
-
-			Set<EventListener> copyOfEventHandlers = new HashSet<EventListener>(
-					this.eventHandlers.get(source));
-
-			for (EventListener eventHandler : copyOfEventHandlers) {
-
-				this.logger.log(Level.FINE, "Informing event listener "
-						+ eventHandler + " about recently observed event "
-						+ event + " from source " + source + "!");
-				eventHandler.handleEvent(event);
-			}
-		}
-
-		// log exiting
-		this.logger.exiting(this.getClass().getName(), "observeEvent");
-	}
-
-}
+}

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/NetworkImpl.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/NetworkImpl.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/NetworkImpl.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -1,8 +1,3 @@
-/*
- * NOTICE: This file is still work in progress. As you can see the Java
- * documentation is written partly in German and in English and logging and
- * documentation still need some work. Sorry for any inconvenience!  
- */
 package de.uniba.wiai.lspi.puppetor.impl;
 
 import java.io.File;
@@ -24,92 +19,526 @@
 import de.uniba.wiai.lspi.puppetor.ServerApplication;
 import de.uniba.wiai.lspi.puppetor.TorProcessException;
 
+/**
+ * Implementation of <code>Network</code>.
+ * 
+ * @author kloesing
+ */
 public class NetworkImpl implements Network {
 
-	private EventManagerImpl eventManager;
+	/**
+	 * Internal thread class that is used to determine fingerprints in parallel.
+	 */
+	private class FingerprintThread extends Thread {
 
-	@Override
-	public String toString() {
-		return this.getClass().getSimpleName() + ": networkName=\""
-				+ this.networkName + "\", networkState="
-				+ this.networkState.toString() + ", nodes.size()="
-				+ this.nodes.size();
+		/**
+		 * The exception, if one is caught while trying to determine the
+		 * fingerprint of the node.
+		 */
+		private TorProcessException caughtException = null;
+
+		/**
+		 * The node of which the fingerprint shall be determined.
+		 */
+		private RouterNode node = null;
+
+		/**
+		 * Creates a new thread to determine the fingerprint of
+		 * <code>node</code>.
+		 * 
+		 * @param node
+		 *            The node of which the fingerprint shall be determined.
+		 */
+		FingerprintThread(RouterNode node) {
+
+			// log entering
+			logger.entering(this.getClass().getName(), "FingerprintThread");
+
+			// remember node reference
+			this.node = node;
+
+			// log exiting
+			logger.exiting(this.getClass().getName(), "FingerprintThread");
+		}
+
+		@Override
+		public void run() {
+
+			// log entering
+			logger.entering(this.getClass().getName(), "run");
+
+			// determine fingerprint
+			try {
+				node.determineFingerprint();
+			} catch (TorProcessException e) {
+				logger.log(Level.SEVERE,
+						"Caught an exception while determining fingerprint for "
+								+ "node " + node.toString() + "!");
+				this.caughtException = e;
+			}
+
+			// log exiting
+			logger.exiting(this.getClass().getName(), "run");
+		}
 	}
 
+	/**
+	 * Internal thread class that is used to start Tor processes in parallel.
+	 */
+	private class NodeStarter extends Thread {
+
+		/**
+		 * The exception, if one is caught while trying to start the node.
+		 */
+		TorProcessException caughtException;
+
+		/**
+		 * The maximum time to wait for the Tor process to start in
+		 * milliseconds.
+		 */
+		private long maximumTimeToWaitInMillis;
+
+		/**
+		 * The node for which the Tor process shall be started.
+		 */
+		private ProxyNode node;
+
+		/**
+		 * Flag that denotes whether starting the Tor process was successful.
+		 */
+		boolean success = false;
+
+		/**
+		 * Creates a new <code>NodeStarter</code> for node <code>node</code>
+		 * that will wait for <code>maximumTimeToWaitInMillis</code>
+		 * milliseconds to start a Tor process, but that is not started, yet.
+		 * 
+		 * @param node
+		 *            The node for which the Tor process shall be started.
+		 * @param maximumTimeToWaitInMillis
+		 *            The maximum time to wait for the Tor process to start in
+		 *            milliseconds.
+		 */
+		NodeStarter(ProxyNode node, long maximumTimeToWaitInMillis) {
+
+			// log entering
+			logger.entering(this.getClass().getName(), "NodeStarter",
+					new Object[] { node, maximumTimeToWaitInMillis });
+
+			// store parameters
+			this.node = node;
+			this.maximumTimeToWaitInMillis = maximumTimeToWaitInMillis;
+
+			// log exiting
+			logger.exiting(this.getClass().getName(), "NodeStarter");
+		}
+
+		@Override
+		public void run() {
+
+			// log entering
+			logger.entering(this.getClass().getName(), "run");
+
+			try {
+				// try to start node
+				this.success = this.node
+						.startNode(this.maximumTimeToWaitInMillis);
+			} catch (TorProcessException e) {
+				// if an exception is caught, store it, but don't throw it (the
+				// thread wouldn't care)
+				this.caughtException = e;
+			}
+
+			// log exiting
+			logger.exiting(this.getClass().getName(), "run");
+		}
+	}
+
+	/**
+	 * The fingerprints of all approved routers in the network configuration.
+	 */
+	private HashSet<String> approvedRoutersFingerprints;
+
+	/**
+	 * The fingerprints of all authoritative directories in the network
+	 * configuration.
+	 */
+	private Set<String> authorizedDirectoriesFingerprints;
+
+	/**
+	 * Event manager to which all events concerning this network are notified.
+	 */
+	private EventManagerImpl eventManager;
+
+	/**
+	 * Logger for this <code>NetworkImpl</code> instance which is called
+	 * "network." plus the name of this network.
+	 */
 	private Logger logger;
 
 	/**
-	 * Contains the name of this node configuration which is the String
-	 * conversion of System.currentTimeMillis().
+	 * Contains the name of this network configuration which is the String
+	 * conversion of System.currentTimeMillis() of the network creation time.
 	 */
-	protected String networkName;
+	private String networkName;
 
 	/**
+	 * The state of this network.
+	 */
+	private NetworkState networkState = NetworkState.CONFIGURING_NODES;
+
+	/**
+	 * All nodes contained in this network. It is important that we store and
+	 * work only with interface types to assure that all operations could also
+	 * be performed by the application itself.
+	 */
+	private Set<ProxyNode> nodes = new HashSet<ProxyNode>();
+
+	/**
+	 * Directory that contains status information of all nodes contained in this
+	 * network.
+	 */
+	private File workingDir;
+
+	/**
 	 * Creates an initially unpopulated Tor network and creates a new working
 	 * directory for it at test-env/randomTestID/.
 	 * 
 	 * @param networkName
-	 *            Name of this network configuration.
-	 * @param logToConsole
-	 *            Whether logging statements shall be written to the console or
-	 *            to a file.
+	 *            Name of this network configuration. May neither be
+	 *            <code>null</code> or a zero-length string.
+	 * @throws IllegalArgumentException
+	 *             Thrown if the given <code>networkName</code> is either
+	 *             <code>null</code> or a zero-length string.
 	 */
 	public NetworkImpl(String networkName) {
-		
-//		 TODO make sure that name is loggable!!
-		
+
+		// check if networkName can be used as logger name
+		if (networkName == null || networkName.length() == 0) {
+			throw new IllegalArgumentException("Invalid networkName: "
+					+ networkName);
+		}
+
+		// create logger
 		this.logger = Logger.getLogger("network." + networkName);
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "NetworkImpl",
+				networkName);
+
+		// TODO is this necessary?!
 		this.logger.setLevel(Level.ALL);
+
+		// remember parameter
 		this.networkName = networkName;
+
+		// create working directory
 		this.workingDir = new File("test-env/" + System.currentTimeMillis());
 		this.workingDir.mkdirs();
+		this.logger.log(Level.FINE, "Created working directory \""
+				+ this.workingDir.getAbsolutePath() + "\"");
 
 		// TODO if we want to log to file, set this... somehow...
 		// this.logFile = new File(this.workingDir.getAbsolutePath()
 		// + "\\events.log");
 
+		// create event manager
 		this.eventManager = new EventManagerImpl(this.networkName);
-	}
 
-	public NetworkState getNetworkState() {
-		// TODO Auto-generated method stub
-		throw new UnsupportedOperationException(
-				"Auto-generated method stub in NetworkImpl.getNetworkState");
+		// log exiting
+		this.logger.exiting(this.getClass().getName(), "NetworkImpl");
 	}
 
+	/**
+	 * Returns whether all nodes in this network are up, or not.
+	 * 
+	 * @return <code>true</code> if all nodes are up, <code>false</code> if
+	 *         at least one node is not up.
+	 */
 	private boolean allNodesUp() {
 
-		// check if all nodes are up
+		// log entering
+		this.logger.entering(this.getClass().getName(), "allNodesUp");
+
+		// nodes can only be up, when network is in state
+		// NetworkState.NODES_STARTED.
+		if (this.networkState != NetworkState.NODES_STARTED) {
+
+			// log exiting and return false
+			this.logger.exiting(this.getClass().getName(), "allNodesUp");
+			return false;
+		}
+
+		// fail on first node that is not up
 		for (ProxyNode node : this.nodes) {
 			if (!eventManager.hasEventOccured(node, Event.NODE_CIRCUIT_OPENED)) {
+
+				// log exiting and return false
+				this.logger.exiting(this.getClass().getName(), "allNodesUp");
 				return false;
 			}
 		}
+
+		// log exiting and return true
+		this.logger.exiting(this.getClass().getName(), "allNodesUp");
 		return true;
 	}
 
+	public void configureAsPrivateNetwork() throws TorProcessException {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(),
+				"configureAsPrivateNetwork");
+
+		// start threads to determine fingerprints for all directories and
+		// routers in parallel
+		Set<FingerprintThread> fingerprintThreads = new HashSet<FingerprintThread>();
+		for (ProxyNode node : nodes) {
+			if (node instanceof RouterNode) {
+				RouterNode dirOrRouterNode = (RouterNode) node;
+				FingerprintThread fingerprintThread = new FingerprintThread(
+						dirOrRouterNode);
+				fingerprintThread.setName(node.getNodeName()
+						+ " Fingerprint Resolver");
+				fingerprintThreads.add(fingerprintThread);
+				fingerprintThread.start();
+			}
+		}
+
+		// wait for all fingerprints have been determined
+		for (FingerprintThread fingerprintThread : fingerprintThreads) {
+
+			// join fingerprint determination one after the other
+			try {
+				fingerprintThread.join();
+			} catch (InterruptedException e) {
+				// ignore; TODO really?!
+				logger.log(Level.WARNING,
+						"Joining fingerprint thread was interrupted.");
+			}
+
+			// if any thread has caught an exception, throw that exception now
+			if (fingerprintThread.caughtException != null) {
+				this.logger.throwing(this.getClass().getName(),
+						"configureAsPrivateNetwork",
+						fingerprintThread.caughtException);
+				throw fingerprintThread.caughtException;
+			}
+		}
+
+		// read DirServer strings for all directories from memory; they should
+		// have been read from disk before, so that this will perform really
+		// fast
+		this.authorizedDirectoriesFingerprints = new HashSet<String>();
+		for (ProxyNode node : this.nodes) {
+			if (node instanceof DirectoryNode) {
+				DirectoryNode dirNode = (DirectoryNode) node;
+				this.authorizedDirectoriesFingerprints.add(dirNode
+						.determineDirServerString());
+			}
+
+		}
+
+		// configure nodes
+		for (ProxyNode node : this.nodes) {
+			if (node.getNodeState() == NodeState.CONFIGURING) {
+				node
+						.configureDirServers(this.authorizedDirectoriesFingerprints);
+			}
+		}
+
+		// read fingerprints for all directories and routers from memory; they
+		// should have been read from disk before, so that this will perform
+		// really fast
+		this.approvedRoutersFingerprints = new HashSet<String>();
+		for (ProxyNode node : this.nodes) {
+			if (node instanceof RouterNode) {
+				RouterNode routerOrDirNode = (RouterNode) node;
+				this.approvedRoutersFingerprints.add(routerOrDirNode
+						.determineFingerprint());
+			}
+		}
+		
+		// write fingerprints for all directories and routers to
+		// approved-routers file
+		for (ProxyNode node : this.nodes) {
+			if (node instanceof DirectoryNode) {
+				DirectoryNode dirNode = (DirectoryNode) node;
+				dirNode.writeApprovedRouters(this.approvedRoutersFingerprints);
+			}
+		}
+
+		// log exiting
+		this.logger.exiting(this.getClass().getName(),
+				"configureAsPrivateNetwork");
+	}
+
+	public ClientApplication createClient(String clientApplicationName,
+			String targetAddress, int targetPort, int socksPort) {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "createClient",
+				new Object[] { clientApplicationName, targetAddress,
+						targetPort, socksPort });
+
+		// create client; parameter checking is done in constructor
+		ClientApplicationImpl client = new ClientApplicationImpl(this,
+				clientApplicationName, targetAddress, targetPort, socksPort);
+
+		// log exiting and return client
+		this.logger.exiting(this.getClass().getName(), "createClient", client);
+		return client;
+	}
+
+	public DirectoryNode createDirectory(String nodeName, int controlPort,
+			int socksPort, int orPort, int dirPort) {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "createDirectory",
+				new Object[] { nodeName, controlPort, socksPort, orPort,
+						dirPort });
+
+		// check state
+		if (this.networkState != NetworkState.CONFIGURING_NODES) {
+			IllegalStateException e = new IllegalStateException();
+			this.logger.throwing(this.getClass().getName(), "createDirectory",
+					e);
+			throw e;
+		}
+
+		// create directory node; parameter checking is done in constructor
+		DirectoryNode dir = new DirectoryNodeImpl(this, nodeName, controlPort,
+				socksPort, orPort, dirPort);
+
+		// add new directory node to nodes collection
+		this.nodes.add(dir);
+
+		// log exiting and return directory node
+		this.logger.exiting(this.getClass().getName(), "createDirectory", dir);
+		return dir;
+	}
+
+	public ProxyNode createProxy(String nodeName, int controlPort, int socksPort) {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "createProxy",
+				new Object[] { nodeName, controlPort, socksPort });
+
+		// check state
+		if (this.networkState != NetworkState.CONFIGURING_NODES) {
+			IllegalStateException e = new IllegalStateException();
+			this.logger.throwing(this.getClass().getName(), "createProxy", e);
+			throw e;
+		}
+
+		// create proxy node; parameter checking is done in constructor
+		ProxyNodeImpl proxy = new ProxyNodeImpl(this, nodeName, controlPort,
+				socksPort);
+
+		// add new proxy node to nodes collection
+		this.nodes.add(proxy);
+
+		// log exiting and return proxy node
+		this.logger.exiting(this.getClass().getName(), "createProxy", proxy);
+		return proxy;
+	}
+
+	public RouterNode createRouter(String nodeName, int controlPort,
+			int socksPort, int orPort, int dirPort) {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "createRouter",
+				new Object[] { nodeName, controlPort, socksPort, orPort,
+						dirPort });
+
+		// check state
+		if (this.networkState != NetworkState.CONFIGURING_NODES) {
+			IllegalStateException e = new IllegalStateException();
+			this.logger.throwing(this.getClass().getName(), "createRouter", e);
+			throw e;
+		}
+
+		// create router node; parameter checking is done in constructor
+		RouterNode router = new RouterNodeImpl(this, nodeName, controlPort,
+				socksPort, orPort, dirPort);
+
+		// add new router node to nodes collection
+		this.nodes.add(router);
+
+		// log exiting and return router node
+		this.logger.exiting(this.getClass().getName(), "createRouter", router);
+		return router;
+	}
+
+	public ServerApplication createServer(String serverApplicationName,
+			int serverPort) {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "createServer",
+				new Object[] { serverApplicationName, serverPort });
+
+		// create server; parameter checking is done in constructor
+		ServerApplicationImpl server = new ServerApplicationImpl(this,
+				serverApplicationName, serverPort);
+
+		// log exiting and return server
+		this.logger.exiting(this.getClass().getName(), "createServer", server);
+		return server;
+	}
+
+	public EventManager getEventManager() {
+		return this.eventManager;
+	}
+
 	/**
-	 * check, (wait, check, hup)*
+	 * Returns the implementation instance of the event manager of this network.
 	 * 
-	 * if all nodes get up during sleeping, we will wake up and return
-	 * immediately
+	 * @return The implementation instance of the event manager of this network.
+	 */
+	EventManagerImpl getEventManagerImpl() {
+		return this.eventManager;
+	}
+
+	public NetworkState getNetworkState() {
+		return this.networkState;
+	}
+
+	/**
+	 * Returns the working directory of this network configuration which is in
+	 * test-env/networkName/.
 	 * 
-	 * @param retries
-	 * @param hupInterval
-	 * @throws Exception
+	 * @return Working directory of this network.
 	 */
-	public boolean hupUntilUp(int retries, long hupInterval)
+	File getWorkingDir() {
+		return workingDir;
+	}
+
+	public boolean hupUntilUp(int tries, long hupInterval)
 			throws TorProcessException {
 
+		// log entering
+		this.logger.entering(this.getClass().getName(), "hupUntilUp",
+				new Object[] { tries, hupInterval });
+
+		// check state
+		if (this.networkState != NetworkState.NODES_STARTED) {
+			IllegalStateException e = new IllegalStateException();
+			this.logger.throwing(this.getClass().getName(), "hupUntilUp", e);
+			throw e;
+		}
+
+		// check if nodes are already up; if so, return immediately
 		if (allNodesUp()) {
+
+			// log exiting and return true
+			this.logger.exiting(this.getClass().getName(), "hupUntilUp", true);
 			return true;
 		}
 
-		// register event handlers
+		// create and register a new event handler for each node
 		final Thread sleepingThread = Thread.currentThread();
 		for (ProxyNode node : this.nodes) {
 			eventManager.addEventListener(node, new EventListener() {
-
 				public void handleEvent(Event event) {
 					if (event == Event.NODE_CIRCUIT_OPENED) {
 						sleepingThread.interrupt();
@@ -119,22 +548,30 @@
 			});
 		}
 
-		for (int i = 0; i < retries; i++) {
+		// walk through wait-check-hup loop until there are no tries left
+		for (int i = 0; i < tries; i++) {
 
 			// determine how long to sleep
 			long endOfSleeping = System.currentTimeMillis() + hupInterval;
 			long now;
 
+			// unless all nodes have reported to be up, wait for the given
+			// maximum time
 			while ((now = System.currentTimeMillis()) < endOfSleeping) {
 
 				// sleep
 				try {
 					Thread.sleep(endOfSleeping - now);
 				} catch (InterruptedException e) {
+					// do nothing about it
 				}
 
-				// check
+				// check if nodes are up now
 				if (allNodesUp()) {
+
+					// log exiting and return true
+					this.logger.exiting(this.getClass().getName(),
+							"hupUntilUp", true);
 					return true;
 				}
 			}
@@ -147,15 +584,27 @@
 			// continue in loop
 		}
 
-		// no retries left and not all nodes are up; return failure
+		// no retries left and not all nodes are up; log exiting and return
+		// failure
+		this.logger.exiting(this.getClass().getName(), "hupUntilUp", false);
 		return false;
-
 	}
 
 	public void shutdownNodes() throws TorProcessException {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "shutdownNodes");
+
+		// check state
 		if (this.networkState != NetworkState.NODES_STARTED) {
-			throw new IllegalStateException();
+			IllegalStateException e = new IllegalStateException();
+			this.logger.throwing(this.getClass().getName(), "shutdownNodes", e);
+			throw e;
 		}
+
+		// iteratively shut down all nodes; if an exception is caught, continue
+		// shutting down the other nodes and throw the first exception
+		// subsequently
 		TorProcessException firstCaughtException = null;
 		for (ProxyNode node : this.nodes) {
 			try {
@@ -166,46 +615,41 @@
 				}
 			}
 		}
+
+		// change network state
 		this.networkState = NetworkState.NODES_SHUT_DOWN;
+
+		// if an exception was caught during shutting down nodes, throw the
+		// first caught exception
 		if (firstCaughtException != null) {
+			this.logger.throwing(this.getClass().getName(), "shutdownNodes",
+					firstCaughtException);
 			throw firstCaughtException;
 		}
-	}
 
-	private static class NodeStarter extends Thread {
-
-		TorProcessException caughtException;
-
-		private long maximumTimeToWaitInMillis;
-
-		private ProxyNode node;
-
-		boolean success = false;
-
-		NodeStarter(ProxyNode node, long maximumTimeToWaitInMillis) {
-			this.node = node;
-			this.maximumTimeToWaitInMillis = maximumTimeToWaitInMillis;
-		}
-
-		@Override
-		public void run() {
-			try {
-				this.success = this.node
-						.startNode(this.maximumTimeToWaitInMillis);
-			} catch (TorProcessException e) {
-				this.caughtException = e;
-			}
-		}
+		// log exiting
+		this.logger.exiting(this.getClass().getName(), "shutdownNodes");
 	}
 
 	public boolean startNodes(long maximumTimeToWaitInMillis)
 			throws TorProcessException {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "startNodes",
+				maximumTimeToWaitInMillis);
+
+		// check state
 		if (this.networkState != NetworkState.CONFIGURATIONS_WRITTEN) {
-			throw new IllegalStateException();
+			IllegalStateException e = new IllegalStateException();
+			this.logger.throwing(this.getClass().getName(), "startNodes", e);
+			throw e;
 		}
 
+		// check parameter
 		if (maximumTimeToWaitInMillis < 0) {
-			throw new IllegalArgumentException();
+			IllegalArgumentException e = new IllegalArgumentException();
+			this.logger.throwing(this.getClass().getName(), "startNodes", e);
+			throw e;
 		}
 
 		// remember time when we begin starting the nodes
@@ -220,27 +664,45 @@
 			nodeStarter.start();
 		}
 
+		// wait for all node starts to complete
 		for (NodeStarter nodeStarter : allNodeStarters) {
+
+			// join node starts one after the other
 			try {
 				nodeStarter.join();
 			} catch (InterruptedException e) {
-				// we have some kind of problem here!
+				// this happens?! we have some kind of problem here!
+				this.logger.log(Level.WARNING,
+						"Interrupt while joining node starter!");
+
+				// log exiting and return false
+				this.logger.exiting(this.getClass().getName(), "startNodes",
+						false);
 				return false;
 			}
+
+			// if node start threw an exception, throw that exception now
 			if (nodeStarter.caughtException != null) {
-				this.networkState = NetworkState.NODES_SHUT_DOWN;
+				this.logger.throwing(this.getClass().getName(), "startNodes",
+						nodeStarter.caughtException);
 				throw nodeStarter.caughtException;
 			}
+
+			// if node start did not succeed in the given time, fail
 			if (!nodeStarter.success) {
 				this.logger.log(Level.WARNING,
 						"Starting nodes was not successful in "
 								+ (maximumTimeToWaitInMillis / 1000)
 								+ " seconds.", this.networkName);
+
+				// log exiting and return false
+				this.logger.exiting(this.getClass().getName(), "startNodes",
+						false);
 				return false;
 			}
 		}
 
-		// check how long we took to start all nodes
+		// determine how long we took to start all nodes
 		long after = System.currentTimeMillis();
 		this.logger.log(Level.FINE, "Starting nodes was successful and took "
 				+ ((after - before) / 1000) + " seconds.", this.networkName);
@@ -248,88 +710,33 @@
 		// change state
 		this.networkState = NetworkState.NODES_STARTED;
 
+		// log exiting and return true
+		this.logger.exiting(this.getClass().getName(), "startNodes", true);
 		return true;
 	}
 
-	public ClientApplication createClient(String clientApplicationName,
-			String targetAddress, int targetPort, int socksPort) {
-		return new ClientApplicationImpl(this, clientApplicationName,
-				targetAddress, targetPort, socksPort);
+	@Override
+	public String toString() {
+		return this.getClass().getSimpleName() + ": networkName=\""
+				+ this.networkName + "\", networkState="
+				+ this.networkState.toString() + ", nodes.size()="
+				+ this.nodes.size();
 	}
 
-	public ProxyNode createProxy(String nodeName, int controlPort, int socksPort) {
+	public void writeConfigurations() throws TorProcessException {
 
-		// TODO check parms
+		// log entering
+		this.logger.entering(this.getClass().getName(), "writeConfigurations");
 
-		ProxyNodeImpl proxy = new ProxyNodeImpl(this, nodeName, controlPort,
-				socksPort);
-
-		// add to nodes
-		this.nodes.add(proxy);
-
-		return proxy;
-	}
-
-	public DirectoryNode createDirectory(String nodeName, int controlPort,
-			int socksPort, int orPort, int dirPort) {
-
-		DirectoryNode dir = new DirectoryNodeImpl(this, nodeName, controlPort,
-				socksPort, orPort, dirPort);
-
-		this.nodes.add(dir);
-
-		return dir;
-	}
-
-	public RouterNode createRouter(String nodeName, int controlPort,
-			int socksPort, int orPort, int dirPort) {
-		RouterNode router = new RouterNodeImpl(this, nodeName, controlPort,
-				socksPort, orPort, dirPort);
-
-		this.nodes.add(router);
-
-		return router;
-	}
-
-	public ServerApplication createServer(String serverApplicationName,
-			int serverPort) {
-		return new ServerApplicationImpl(this, serverApplicationName,
-				serverPort);
-	}
-
-	public EventManager getEventManager() {
-		return this.eventManager;
-	}
-
-	public EventManagerImpl getEventManagerImpl() {
-		return this.eventManager;
-	}
-
-	private NetworkState networkState = NetworkState.CONFIGURING_NODES;
-
-	/**
-	 * Writes configurations for all nodes in the network, including torrc and
-	 * approved-routers files. Directory nodes are configured first in order to
-	 * obtain their fingerprints for all torrc files. Next are routers to obtain
-	 * their fingerprints for the directories' approved-routers files. Proxies
-	 * are configured at the end.
-	 * 
-	 * This operation can only be invoked, if network status is CONFIGURABLE.
-	 * 
-	 * @throws IllegalStateException
-	 *             If method is invoked in network status other than
-	 *             CONFIGURABLE.
-	 */
-	public void writeConfigurations() throws TorProcessException {
-
 		// check state
 		if (this.networkState != NetworkState.CONFIGURING_NODES) {
-			throw new IllegalStateException();
+			IllegalStateException e = new IllegalStateException();
+			this.logger.throwing(this.getClass().getName(),
+					"writeConfigurations", e);
+			throw e;
 		}
 
-		// TODO don't we need to configure the nodes as private nodes, if we
-		// have a directory node here?!
-
+		// write configurations for all nodes
 		for (ProxyNode node : this.nodes) {
 			if (node.getNodeState() == NodeState.CONFIGURING) {
 				node.writeConfiguration();
@@ -338,124 +745,8 @@
 
 		// change state
 		this.networkState = NetworkState.CONFIGURATIONS_WRITTEN;
-	}
 
-	/**
-	 * Directory that contains status information of all nodes contained in this
-	 * network, plus the common log file, if one is created.
-	 */
-	protected File workingDir;
-
-	/**
-	 * Returns the working directory of this network configuration which is in
-	 * test-env/networkName/.
-	 * 
-	 * @return Working directory of this network.
-	 */
-	File getWorkingDir() {
-		return workingDir;
+		// log exiting
+		this.logger.exiting(this.getClass().getName(), "writeConfigurations");
 	}
-
-	/**
-	 * All nodes contained in this network. It is important that we store only
-	 * interface types to assure that all operations could also be performed by
-	 * the application itself.
-	 */
-	protected Set<ProxyNode> nodes = new HashSet<ProxyNode>();
-
-	/**
-	 * Internal class that is used to determine fingerprints in parallel.
-	 * 
-	 * 
-	 */
-	private static class FingerprintThread extends Thread {
-
-		private TorProcessException caughtException = null;
-
-		private RouterNode node = null;
-
-		FingerprintThread(RouterNode node) {
-			this.node = node;
-		}
-
-		public void run() {
-			try {
-				node.determineFingerprint();
-			} catch (TorProcessException e) {
-				this.caughtException = e;
-			}
-		}
-	}
-
-	private HashSet<String> approvedRoutersFingerprints;
-
-	Set<String> authorizedDirectoriesFingerprints = new HashSet<String>();
-
-	public void configureAsPrivateNetwork() throws TorProcessException {
-
-		// determine fingerprints for all directories and routers (can be done
-		// in parallel)
-		Set<FingerprintThread> fingerprintThreads = new HashSet<FingerprintThread>();
-		for (ProxyNode node : nodes) {
-			if (node instanceof RouterNode) {
-				RouterNode dirOrRouterNode = (RouterNode) node;
-				FingerprintThread fingerprintThread = new FingerprintThread(
-						dirOrRouterNode);
-				fingerprintThread.setName(node.getNodeName()
-						+ " Fingerprint Resolver");
-				fingerprintThreads.add(fingerprintThread);
-				fingerprintThread.start();
-			}
-		}
-		for (FingerprintThread fingerprintThread : fingerprintThreads) {
-			try {
-				fingerprintThread.join();
-			} catch (InterruptedException e) {
-				// ignore
-				logger.log(Level.WARNING, "fingerprint thread was interrupted.");
-			}
-			if (fingerprintThread.caughtException != null) {
-				throw fingerprintThread.caughtException;
-			}
-		}
-
-		// read DirServer strings for all directories from memory; they should
-		// have been read from disk before, so that this will perform really
-		// fast
-		for (ProxyNode node : this.nodes) {
-			if (node instanceof DirectoryNode) {
-				DirectoryNode dirNode = (DirectoryNode) node;
-				this.authorizedDirectoriesFingerprints.add(dirNode
-						.determineDirServerString());
-			}
-
-		}
-
-		// configure nodes
-		for (ProxyNode node : this.nodes) {
-			if (node.getNodeState() == NodeState.CONFIGURING) {
-				node
-						.configureDirServers(this.authorizedDirectoriesFingerprints);
-			}
-		}
-
-		// read fingerprints for all directories and routers from memory and
-		// write them to approved-routers file; they should have been read from
-		// disk before, so that this will perform really fast
-		this.approvedRoutersFingerprints = new HashSet<String>();
-		for (ProxyNode node : this.nodes) {
-			if (node instanceof RouterNode) {
-				RouterNode routerOrDirNode = (RouterNode) node;
-				this.approvedRoutersFingerprints.add(routerOrDirNode
-						.determineFingerprint());
-			}
-
-		}
-		for (ProxyNode node : this.nodes) {
-			if (node instanceof DirectoryNode) {
-				DirectoryNode dirNode = (DirectoryNode) node;
-				dirNode.writeApprovedRouters(this.approvedRoutersFingerprints);
-			}
-		}
-	}
 }

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ProxyNodeImpl.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ProxyNodeImpl.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ProxyNodeImpl.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -1,19 +1,16 @@
-/*
- * NOTICE: This file is still work in progress. As you can see the Java
- * documentation is written partly in German and in English or needs some work
- * to refine it. This which will be the first thing to change in the next
- * version. Sorry for any inconvenience!  
- */
 package de.uniba.wiai.lspi.puppetor.impl;
 
-import java.io.BufferedInputStream;
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.io.OutputStream;
 import java.net.Socket;
 import java.util.ArrayList;
 import java.util.List;
@@ -29,21 +26,23 @@
 import de.uniba.wiai.lspi.puppetor.TorProcessException;
 
 /**
- * Abstract Java proxy that represents one Tor node (i.e. Tor process) in the
- * testbed network. Can be a Tor proxy, a Tor router, or a Tor directory.
+ * Implementation of <code>ProxyNode</code>.
  * 
  * @author kloesing
  */
 public class ProxyNodeImpl implements ProxyNode {
 
-	// TODO make this configurable
+	/**
+	 * Executable file containing Tor.
+	 * 
+	 * TODO make this configurable!
+	 */
 	protected static final File torExecutable = new File("tor");
 
 	/**
-	 * Logger for this Node instance which is called "node." plus the node's
-	 * name.
+	 * The <code>torrc</code> configuration file of this Tor node.
 	 */
-	protected Logger logger;
+	protected File configFile;
 
 	/**
 	 * Collects all configuration strings for this node during configuration
@@ -51,51 +50,86 @@
 	 */
 	protected List<String> configuration;
 
-	public synchronized NodeState getNodeState() {
-		return this.nodeState;
-	}
+	/**
+	 * Connection via Tor controller.
+	 */
+	protected TorControlConnection conn;
 
-	@Override
-	public String toString() {
-		return this.getClass().getSimpleName() + ": nodeName=\""
-				+ this.nodeName + "\", controlPort=" + this.controlPort
-				+ ", socksPort=" + this.socksPort;
-	}
+	/**
+	 * Port on which the Tor node will be listening for us as its controller.
+	 */
+	protected int controlPort;
 
 	/**
-	 * Port on which node will be listening for SOCKS connections.
+	 * Event manager to which all events concerning this node are notified.
 	 */
+	private EventManagerImpl eventManager;
+
+	/**
+	 * Logger for this <code>ProxyNodeImpl</code> instance which is called
+	 * "node." plus the name of this node.
+	 */
+	protected Logger logger;
+
+	/**
+	 * Network to which this node belongs.
+	 */
+	protected NetworkImpl network;
+
+	/**
+	 * Name of this node that is used as part of the working directory and as
+	 * logger name of this node.
+	 */
+	protected String nodeName;
+
+	/**
+	 * The state of this node.
+	 */
+	protected NodeState nodeState = NodeState.CONFIGURING;
+
+	/**
+	 * Port on which the Tor node will be listening for SOCKS connection
+	 * requests.
+	 */
 	protected int socksPort;
 
-	private EventManagerImpl eventManager;
+	/**
+	 * Handle on the running Tor process that belongs to this node.
+	 */
+	protected Process torProcess;
 
 	/**
-	 * LOGGING OK
+	 * Directory in which all information concerning this node is stored.
+	 */
+	protected File workingDir;
+
+	/**
+	 * Creates a new <code>ProxyNodeImpl</code> and adds it to the given
+	 * <code>network</code>, but does not yet write its configuration to disk
+	 * or start the corresponding Tor process.
 	 * 
-	 * Creates a new node and adds it to the given network. Does not yet create
-	 * a new Tor process.
-	 * 
 	 * @param network
 	 *            Network configuration to which this node belongs.
 	 * @param nodeName
-	 *            The node's name which may only consist of between 1 and 19
-	 *            alpha-numeric characters.
+	 *            The name of the new node which may only consist of between 1
+	 *            and 19 alpha-numeric characters.
 	 * @param controlPort
-	 *            Port on which the Tor process will be listening for us as its
-	 *            controller.
-	 * 
+	 *            Port on which the Tor node will be listening for us as its
+	 *            controller. May not be negative or greater than 65535.
+	 * @param socksPort
+	 *            Port on which the Tor node will be listening for SOCKS
+	 *            connection requests. May not be negative or greater than
+	 *            65535.
 	 * @throws IllegalArgumentException
-	 *             If at least one of the parameters is null or has an invalid
-	 *             value.
+	 *             If at least one of the parameters is <code>null</code> or
+	 *             has an invalid value.
 	 */
-	public ProxyNodeImpl(NetworkImpl network, String nodeName, int controlPort,
+	ProxyNodeImpl(NetworkImpl network, String nodeName, int controlPort,
 			int socksPort) {
 
-		// make sure that name is a valid logger name
+		// make sure that nodeName is a valid logger name
 		if (nodeName == null || nodeName.length() < 1 || nodeName.length() > 19
 				|| !nodeName.matches("[a-zA-Z0-9]*")) {
-
-			// prepare and throw exception
 			String reason = "\"" + nodeName + "\" is not a valid node name!";
 			IllegalArgumentException e = new IllegalArgumentException(reason);
 			throw e;
@@ -112,13 +146,7 @@
 		// check remaining parameters
 		if (network == null || controlPort < 0 || controlPort > 65535
 				|| socksPort < 0 || socksPort > 65535) {
-
-			// prepare and throw exception
-			String reason = "Invalid parameter values: network=" + network
-					+ ", controlPort=" + controlPort + ", socksPort="
-					+ socksPort;
-			IllegalArgumentException e = new IllegalArgumentException(reason);
-			this.logger.log(Level.SEVERE, reason, e);
+			IllegalArgumentException e = new IllegalArgumentException();
 			this.logger.throwing(this.getClass().getName(), "ProxyNodeImpl", e);
 			throw e;
 		}
@@ -132,23 +160,19 @@
 		// obtain reference on event manager from network
 		this.eventManager = network.getEventManagerImpl();
 
-		// determine working directory
+		// create working directory
 		this.workingDir = new File(this.network.getWorkingDir()
 				.getAbsolutePath()
 				+ File.separator + nodeName + File.separator);
-
-		// create working directory
-		this.logger.log(Level.FINER, "Creating working directory \""
-				+ this.workingDir + "\"...");
 		this.workingDir.mkdirs();
 		this.logger.log(Level.FINE, "Created working directory \""
-				+ this.workingDir + "\"!");
+				+ this.workingDir.getAbsolutePath() + "\"");
 
 		// create reference on config file
 		this.configFile = new File(this.workingDir.getAbsolutePath()
 				+ File.separator + "torrc");
 
-		// initialize configuration with general-purpose configurations
+		// initialize configuration with general-purpose configuration entries
 		this.configuration = new ArrayList<String>();
 		this.configuration.add("DataDirectory .");
 		this.configuration.add("SafeLogging 0");
@@ -176,6 +200,10 @@
 		this.configuration
 				.add("AllowInvalidNodes middle,rendezvous,exit,entry,introduction");
 
+		// tunnel dir connections
+		// this.configuration.add("TunnelDirConns 1");
+		// this.configuration.add("PreferTunneledDirConns 1");
+
 		// initialize state
 		this.nodeState = NodeState.CONFIGURING;
 
@@ -184,11 +212,180 @@
 
 	}
 
+	public void addConfiguration(String configurationString) {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "addConfiguration");
+
+		// check state
+		if (this.nodeState != NodeState.CONFIGURING) {
+			IllegalStateException e = new IllegalStateException();
+			this.logger.throwing(this.getClass().getName(), "addConfiguration",
+					e);
+			throw e;
+		}
+
+		// check parameter
+		if (configurationString == null || configurationString.length() < 1) {
+			IllegalArgumentException e = new IllegalArgumentException();
+			this.logger.throwing(this.getClass().getName(), "addConfiguration",
+					e);
+			throw e;
+		}
+
+		// add configuration string
+		this.configuration.add(configurationString);
+
+		// log exiting
+		this.logger.exiting(this.getClass().getName(), "addConfiguration");
+	}
+
+	public synchronized void addHiddenService(String serviceName,
+			int servicePort, int virtualPort) {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "addHiddenService",
+				new Object[] { serviceName, servicePort, virtualPort });
+
+		// check state
+		if (this.nodeState != NodeState.CONFIGURING) {
+			this.logger.log(Level.SEVERE,
+					"Hidden service can only be added when node is in state "
+							+ "CONFIGURING!");
+			IllegalStateException e = new IllegalStateException(
+					"Hidden service can only be added when node is in state "
+							+ "CONFIGURING!");
+			this.logger.throwing(this.getClass().getName(), "addHiddenService",
+					e);
+			throw e;
+		}
+
+		// check parameters
+		if (serviceName == null || serviceName.length() == 0 || servicePort < 0
+				|| servicePort > 65535 || virtualPort < 0
+				|| virtualPort > 65535) {
+			this.logger.log(Level.SEVERE,
+					"Illegal argument when adding hidden service!");
+			IllegalArgumentException e = new IllegalArgumentException();
+			this.logger.throwing(this.getClass().getName(), "addHiddenService",
+					e);
+			throw e;
+		}
+
+		// add hidden service using Tor controller
+		this.configuration.add("HiddenServiceDir "
+				+ workingDir.getAbsolutePath() + File.separator + serviceName
+				+ "\nHiddenServicePort " + virtualPort + " 127.0.0.1:"
+				+ servicePort);
+
+		// log exiting
+		this.logger.exiting(this.getClass().getName(), "addHiddenService");
+	}
+
 	/**
-	 * LOGGING OK
+	 * Adds a hidden service configuration to this node while the node is
+	 * running.
 	 * 
-	 * @see de.uniba.wiai.lspi.puppetor.ProxyNode#configureDirServers(java.util.Set)
+	 * TODO not fully implemented yet, but this should be possible both, during
+	 * configuration and when running a network...
+	 * 
+	 * @param serviceName
+	 *            Name of the hidden service that will be used as name for the
+	 *            hidden service directory. May neither be <code>null</code>
+	 *            or a zero-length string.
+	 * @param servicePort
+	 *            The TCP port on which the service will be available for
+	 *            requests. This can, but need not be different from the virtual
+	 *            port that is announced to clients. May not be negative or
+	 *            greater than 65535.
+	 * @param virtualPort
+	 *            The virtual TCP port that this hidden service runs on as it is
+	 *            announced to clients. May not be negative or greater than
+	 *            65535.
+	 * @return The onion address string consisting of 16 base32 chars plus
+	 *         ".onion" for hidden service versions 0 and 1 or 16 base32 chars
+	 *         plus "." plus 24 base32 chars plus ".onion" for hidden service
+	 *         version 2.
 	 */
+	synchronized String addHiddenServiceUsingController(String serviceName,
+			int servicePort, int virtualPort) {
+
+		// TODO this method is not supported yet!
+		if (1 != 2) {
+			UnsupportedOperationException e = new UnsupportedOperationException();
+			this.logger.throwing(this.getClass().getName(),
+					"addHiddenServiceUsingController", e);
+			throw e;
+		}
+
+		// log entering
+		this.logger.entering(this.getClass().getName(),
+				"addHiddenServiceUsingController", new Object[] { serviceName,
+						servicePort, virtualPort });
+
+		// TODO check state
+
+		// check parameters
+		if (serviceName == null || serviceName.length() == 0 || servicePort < 0
+				|| servicePort > 65535 || virtualPort < 0
+				|| virtualPort > 65535) {
+			IllegalArgumentException e = new IllegalArgumentException();
+			this.logger.throwing(this.getClass().getName(),
+					"addHiddenServiceUsingController", e);
+			throw e;
+		}
+
+		// String serverName = server.getServerName();
+		// int serverPort = server.getServerPort();
+
+		// add hidden service using Tor controller
+		this.logger.log(Level.FINE,
+				"Adding hidden service using Tor controller.");
+
+		List<String> configs = new ArrayList<String>();
+		configs.add("HiddenServiceDir " + workingDir.getAbsolutePath() + "/"
+				+ serviceName);
+		configs.add("HiddenServicePort " + virtualPort + " 127.0.0.1:"
+				+ servicePort);
+		try {
+			conn.setConf(configs);
+		} catch (IOException e) {
+			RuntimeException ex = new RuntimeException(
+					"IOException when trying to register a new "
+							+ "hidden service", e);
+			this.logger.throwing(this.getClass().getName(),
+					"addHiddenServiceUsingController", ex);
+			throw ex;
+		}
+		this.logger.log(Level.FINE,
+				"Hidden service successfully registered at Tor proxy.");
+
+		// 
+		File hiddenServiceFile = new File(workingDir.getAbsolutePath() + "\\"
+				+ serviceName + "\\hostname");
+		if (!hiddenServiceFile.exists()) {
+			RuntimeException ex = new RuntimeException();
+			this.logger.throwing(this.getClass().getName(),
+					"addHiddenServiceUsingController", ex);
+			throw ex;
+		}
+		// read hostname from file
+		String address = null;
+		try {
+			BufferedReader br = new BufferedReader(new FileReader(
+					hiddenServiceFile));
+			address = br.readLine();
+			br.close();
+		} catch (IOException e) {
+			RuntimeException ex = new RuntimeException(e);
+			this.logger.throwing(this.getClass().getName(),
+					"addHiddenServiceUsingController", ex);
+			throw ex;
+		}
+
+		return address;
+	}
+
 	public synchronized void configureDirServers(
 			Set<String> authorizedDirServerStrings) {
 
@@ -198,55 +395,194 @@
 
 		// check parameter
 		if (authorizedDirServerStrings == null) {
-
-			// prepare and throw exception
-			String reason = "Parameter may not be null!";
-			IllegalArgumentException e = new IllegalArgumentException(reason);
-			this.logger.log(Level.SEVERE, reason, e);
+			IllegalArgumentException e = new IllegalArgumentException(
+					"Parameter may not be null!");
 			this.logger.throwing(this.getClass().getName(),
 					"configureDirServers", e);
 			throw e;
 		}
 
 		// add to configuration
+		int entriesBefore = this.configuration.size();
 		this.configuration.addAll(authorizedDirServerStrings);
 		this.logger.log(Level.FINE, "Added "
 				+ authorizedDirServerStrings.size()
-				+ " DirServer entries to configuration!");
+				+ " DirServer entries to configuration, having "
+				+ entriesBefore + " entries before and "
+				+ this.configuration.size()
+				+ " entries afterwards (duplicates possible)!");
 
 		// log exiting
 		this.logger.exiting(this.getClass().getName(), "configureDirServers");
+	}
 
+	public synchronized void copyDescriptorTo(ProxyNode otherNode)
+			throws TorProcessException {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "copyDescriptorTo",
+				otherNode);
+
+		// copy files
+		try {
+			File otherWorkingDir = ((ProxyNodeImpl) otherNode).workingDir;
+			for (File f : workingDir.listFiles()) {
+				if (f.getName().contains(".rsd")) {
+					File dst = new File(otherWorkingDir.getAbsolutePath()
+							+ File.separator + f.getName());
+					this.logger.log(Level.FINE, "Copying '"
+							+ f.getAbsolutePath() + "' to '"
+							+ dst.getAbsolutePath() + "'...");
+					InputStream in = new FileInputStream(f);
+					OutputStream out = new FileOutputStream(dst);
+					byte[] buf = new byte[1024];
+					int len;
+					while ((len = in.read(buf)) > 0) {
+						out.write(buf, 0, len);
+					}
+					in.close();
+					out.close();
+				}
+			}
+		} catch (IOException e) {
+			TorProcessException ex = new TorProcessException(
+					"Error copying descriptors");
+			this.logger.throwing(this.getClass().getName(), "copyDescriptorTo",
+					ex);
+			throw ex;
+		}
+
+		// log exiting
+		this.logger.exiting(this.getClass().getName(), "copyDescriptorTo");
 	}
 
-	/**
-	 * Network to which this node belongs.
-	 */
-	protected NetworkImpl network;
+	public synchronized String getNodeName() {
+		return this.nodeName;
+	}
 
-	/**
-	 * Name of this node that is used as part of the node's working directory
-	 * and logger.
-	 */
-	protected String nodeName;
+	public synchronized NodeState getNodeState() {
+		return this.nodeState;
+	}
 
-	/**
-	 * Port on which the process will be listening for us as its controller.
-	 */
-	protected int controlPort;
+	public synchronized String getOnionAddress(String serviceName, int version)
+			throws TorProcessException {
 
-	/**
-	 * Directory in which all information concerning this node is stored.
-	 */
-	protected File workingDir;
+		// log entering
+		this.logger.entering(this.getClass().getName(), "getOnionAddress",
+				new Object[] { serviceName, version });
 
-	/**
-	 * LOGGING OK
-	 * 
-	 * @param maximumTimeToWaitInMillis <
-	 *            0 bedeutet unendlich lange
-	 * 
-	 */
+		// check parameter
+		if (serviceName == null || serviceName.length() == 0) {
+			IllegalArgumentException e = new IllegalArgumentException();
+			this.logger.throwing(this.getClass().getName(), "getOnionAddress",
+					e);
+			throw e;
+		}
+
+		// check if hidden service directory exists
+		File hiddenServiceFile = new File(workingDir.getAbsolutePath()
+				+ File.separator + serviceName + File.separator + "hostname"
+				+ ((version <= 1) ? "" : "2"));
+		if (!hiddenServiceFile.exists()) {
+			this.logger.log(Level.SEVERE,
+					"Hidden service directory or hostname file does not exist: "
+							+ hiddenServiceFile.getAbsolutePath());
+
+			TorProcessException e = new TorProcessException(
+					"Hidden service directory or hostname file does not exist: "
+							+ hiddenServiceFile.getAbsolutePath());
+			this.logger.throwing(this.getClass().getName(), "getOnionAddress",
+					e);
+			throw e;
+		}
+
+		// read hostname from file
+		String address = null;
+		try {
+			BufferedReader br = new BufferedReader(new FileReader(
+					hiddenServiceFile));
+			address = br.readLine();
+			br.close();
+		} catch (IOException e) {
+			TorProcessException ex = new TorProcessException(
+					"Could not read hostname file!", e);
+			this.logger.throwing(this.getClass().getName(), "getOnionAddress",
+					ex);
+			throw ex;
+		}
+
+		// log exiting and return address
+		this.logger.exiting(this.getClass().getName(), "getOnionAddress",
+				address);
+		return address;
+	}
+
+	public synchronized void hup() throws TorProcessException {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "hup");
+
+		// check state
+		if (this.nodeState != NodeState.RUNNING) {
+			IllegalStateException e = new IllegalStateException(
+					"Cannot hup a process when it's not running!");
+			this.logger.throwing(this.getClass().getName(), "hup", e);
+			throw e;
+		}
+
+		// send HUP signal to Tor process
+		try {
+			this.conn.signal("HUP");
+		} catch (IOException e) {
+			TorProcessException ex = new TorProcessException(
+					"Could not send the command HUP to the Tor process!", e);
+			this.logger.throwing(this.getClass().getName(), "hup", ex);
+			throw ex;
+		} catch (NullPointerException e) {
+			// TODO sometimes, this throws a NullPointerException...
+			this.logger.log(Level.SEVERE,
+					"NullPointerException while sending HUP signal to node "
+							+ this.toString());
+			throw e;
+		}
+
+		// log exiting
+		this.logger.exiting(this.getClass().getName(), "hup");
+	}
+
+	public synchronized void shutdown() throws TorProcessException {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "shutdown");
+
+		// check state
+		if (this.nodeState != NodeState.RUNNING) {
+			IllegalStateException e = new IllegalStateException();
+			this.logger.throwing(this.getClass().getName(), "shutdown", e);
+			throw e;
+		}
+
+		// we cannot simply kill the Tor process, because we have established a
+		// controller connection to it which would interpret a closed socket as
+		// failure and throw a RuntimeException
+		// TODO who cares?!
+		try {
+			this.conn.shutdownTor("SHUTDOWN");
+			this.conn.shutdownTor("SHUTDOWN");
+		} catch (IOException e) {
+			TorProcessException ex = new TorProcessException(
+					"Could not send shutdown command to Tor process!", e);
+			this.logger.throwing(this.getClass().getName(), "shutdown", ex);
+			throw ex;
+		}
+
+		// change state
+		this.nodeState = NodeState.SHUT_DOWN;
+
+		// log exiting
+		this.logger.exiting(this.getClass().getName(), "shutdown");
+	}
+
 	public synchronized boolean startNode(long maximumTimeToWaitInMillis)
 			throws TorProcessException {
 
@@ -256,12 +592,9 @@
 
 		// check state
 		if (this.nodeState != NodeState.CONFIGURATION_WRITTEN) {
-
-			// prepare and throw exception
 			String reason = "Node is not in state "
 					+ "NodeState.CONFIGURATION_WRITTEN!";
 			IllegalStateException e = new IllegalStateException(reason);
-			this.logger.log(Level.SEVERE, reason, e);
 			this.logger.throwing(this.getClass().getName(), "startNode", e);
 			throw e;
 		}
@@ -275,13 +608,10 @@
 			this.torProcess = processBuilder.start();
 			this.logger.log(Level.FINE, "Started Tor process successfully!");
 		} catch (IOException e) {
-
-			// prepare and throw exception
 			String reason = "Could not start Tor process!";
-			TorProcessException e1 = new TorProcessException(reason, e);
-			this.logger.log(Level.SEVERE, reason, e1);
-			this.logger.throwing(this.getClass().getName(), "startNode", e1);
-			throw e1;
+			TorProcessException ex = new TorProcessException(reason, e);
+			this.logger.throwing(this.getClass().getName(), "startNode", ex);
+			throw ex;
 		}
 
 		// start thread to parse output
@@ -294,10 +624,9 @@
 				// log entering
 				logger.entering(this.getClass().getName(), "run");
 
+				// read output from Tor to parse it
 				String line = null;
 				boolean waitingForControlPort = true;
-
-				// read output from Tor
 				try {
 
 					while ((line = br.readLine()) != null) {
@@ -319,7 +648,7 @@
 					// don't throw this exception, nobody will catch it!
 					String reason = "IOException when reading output from Tor "
 							+ "process!";
-					logger.log(Level.FINE, reason, e);
+					logger.log(Level.WARNING, reason, e);
 				}
 
 				// log exiting
@@ -372,11 +701,14 @@
 
 		// be sure that Tor is ready, especially if computer is very busy and
 		// many nodes are created
-		try {
-			Thread.sleep(1000);
-		} catch (InterruptedException e2) {
-		}
-		
+		// TODO don't wait, because we could miss log messages while waiting
+		// TODO should we better only parse the process output instead of
+		// parsing log messages from the controller?!
+		// try {
+		// Thread.sleep(1000);
+		// } catch (InterruptedException e2) {
+		// }
+
 		// connect to the controller
 		this.logger.log(Level.FINER, "Connecting to control port...");
 		try {
@@ -384,13 +716,11 @@
 			this.conn = TorControlConnection.getConnection(controlSocket);
 			this.conn.authenticate(new byte[0]);
 		} catch (IOException e) {
-
-			// prepare and throw exception
-			String reason = "Could not connect to control port " + controlPort + "!";
-			TorProcessException e1 = new TorProcessException(reason, e);
-			this.logger.log(Level.SEVERE, reason, e1);
-			this.logger.throwing(this.getClass().getName(), "startNode", e1);
-			throw e1;
+			String reason = "Could not connect to control port " + controlPort
+					+ "!";
+			TorProcessException ex = new TorProcessException(reason, e);
+			this.logger.throwing(this.getClass().getName(), "startNode", ex);
+			throw ex;
 		}
 		this.logger.log(Level.FINE, "Connected to control port successfully!");
 
@@ -398,14 +728,16 @@
 		EventHandler handler = new EventHandler() {
 
 			public void bandwidthUsed(long read, long written) {
-				logger.log(Level.FINEST, "bandwidthUsed(read, written) = "
-						+ read + ", " + written);
+				// TODO do we need this information?
+				// logger.log(Level.FINEST, "bandwidthUsed(read, written) = "
+				// + read + ", " + written);
 			}
 
 			public void circuitStatus(String status, String circID, String path) {
-				logger.log(Level.FINEST,
-						"circuitStatus(status, circID, path) = " + status
-								+ ", " + circID + ", " + path);
+				// TODO do we need this information?
+				// logger.log(Level.FINEST,
+				// "circuitStatus(status, circID, path) = " + status
+				// + ", " + circID + ", " + path);
 			}
 
 			public void message(String severity, String msg) {
@@ -429,51 +761,50 @@
 			}
 
 			public void newDescriptors(List orList) {
-				StringBuilder sb = new StringBuilder(
-						"newDescriptors(orList) =\n");
-				for (Object o : orList) {
-					sb.append(o + "\n");
-				}
-				logger.log(Level.FINEST, sb.toString());
+				// TODO do we need this information?
+				// StringBuilder sb = new StringBuilder(
+				// "newDescriptors(orList) =\n");
+				// for (Object o : orList) {
+				// sb.append(o + "\n");
+				// }
+				// logger.log(Level.FINEST, sb.toString());
 			}
 
 			public void orConnStatus(String status, String orName) {
-				logger.log(Level.FINEST, "orConnStatus(status, orName) = "
-						+ status + ", " + orName);
+				// TODO do we need this information?
+				// logger.log(Level.FINEST, "orConnStatus(status, orName) = "
+				// + status + ", " + orName);
 			}
 
 			public void streamStatus(String status, String streamID,
 					String target) {
-				logger.log(Level.FINEST,
-						"streamStatus(status, streamID, target) = " + status
-								+ ", " + streamID + ", " + target);
+				// TODO do we need this information?
+				// logger.log(Level.FINEST,
+				// "streamStatus(status, streamID, target) = " + status
+				// + ", " + streamID + ", " + target);
 			}
 
 			public void unrecognized(String type, String msg) {
-				logger.log(Level.FINEST, "unrecognized(type, msg) = " + type
-						+ ", " + msg);
+				// TODO do we need this information?
+				// logger.log(Level.FINEST, "unrecognized(type, msg) = " + type
+				// + ", " + msg);
 			}
 		};
-		conn.setEventHandler(handler);
-		
-		// register for logging events of level INFO and higher
+		this.conn.setEventHandler(handler);
+
+		// register for logging events of level INFO and higher using controller
 		List<String> events = new ArrayList<String>();
 		events.add("INFO");
 		events.add("NOTICE");
 		events.add("WARN");
 		events.add("ERR");
 		try {
-			
-			// register for events using controller
 			this.conn.setEvents(events);
 		} catch (IOException e) {
-
-			// prepare and throw exception
 			String reason = "Could not register event handler at Tor process!";
-			TorProcessException e1 = new TorProcessException(reason, e);
-			this.logger.log(Level.SEVERE, reason, e1);
-			this.logger.throwing(this.getClass().getName(), "startNode", e1);
-			throw e1;
+			TorProcessException ex = new TorProcessException(reason, e);
+			this.logger.throwing(this.getClass().getName(), "startNode", ex);
+			throw ex;
 		}
 		this.logger.log(Level.FINE, "Registered event handler at Tor process!");
 
@@ -485,92 +816,24 @@
 		return true;
 	}
 
-	/**
-	 * Handle on running Tor process.
-	 */
-	protected Process torProcess;
-
-	public synchronized void addHiddenService(String serviceName,
-			int servicePort, int virtualPort) {
-
-		// check state
-		if (this.nodeState != NodeState.CONFIGURING) {
-			this.logger.log(Level.SEVERE,
-					"Hidden service can only be added when node is in state "
-							+ "CONFIGURING!");
-			throw new IllegalStateException(
-					"Hidden service can only be added when node is in state "
-							+ "CONFIGURING!");
-		}
-
-		// check params
-		if (serviceName == null || serviceName.length() == 0 || servicePort < 0
-				|| servicePort > 65535 || virtualPort < 0
-				|| virtualPort > 65535) {
-			this.logger.log(Level.SEVERE,
-					"Illegal argument when adding hidden service!");
-			throw new IllegalArgumentException();
-		}
-
-		// add hidden service using Tor controller
-		this.configuration.add("HiddenServiceDir "
-				+ workingDir.getAbsolutePath() + File.separator + serviceName + "\nHiddenServicePort " + virtualPort
-				+ " 127.0.0.1:" + servicePort);
-
+	@Override
+	public String toString() {
+		return this.getClass().getSimpleName() + ": nodeName=\""
+				+ this.nodeName + "\", controlPort=" + this.controlPort
+				+ ", socksPort=" + this.socksPort;
 	}
 
-	public synchronized String getOnionAddress(String serviceName)
-			throws TorProcessException {
+	public synchronized void writeConfiguration() throws TorProcessException {
 
-		// check parameter
-		if (serviceName == null || serviceName.length() == 0) {
-			this.logger.log(Level.SEVERE, "Illegal argument!");
-			throw new IllegalArgumentException();
-		}
+		// log entering
+		this.logger.entering(this.getClass().getName(), "writeConfiguration");
 
-		// check if hidden service directory exists
-		File hiddenServiceFile = new File(workingDir.getAbsolutePath()
-				+ File.separator + serviceName + File.separator + "hostname");
-		if (!hiddenServiceFile.exists()) {
-			this.logger.log(Level.SEVERE,
-					"Hidden service directory does not exist: "
-							+ hiddenServiceFile.getAbsolutePath());
-			throw new TorProcessException(
-					"Hidden service directory does not exist: "
-							+ hiddenServiceFile.getAbsolutePath());
-		}
-
-		// read hostname from file
-		String address = null;
-		try {
-			// TODO use FileReader
-			FileInputStream fis = new FileInputStream(hiddenServiceFile);
-			BufferedInputStream bis = new BufferedInputStream(fis);
-			byte[] bytes = new byte[16];
-			bis.read(bytes);
-			address = new String(bytes) + ".onion";
-			bis.close();
-		} catch (IOException e) {
-			throw new TorProcessException("Could not read hostname file!", e);
-		}
-
-		return address;
-	}
-
-	/**
-	 * Connection via Tor controller.
-	 */
-	protected TorControlConnection conn;
-
-	protected NodeState nodeState = NodeState.CONFIGURING;
-
-	protected File configFile;
-
-	public synchronized void writeConfiguration() throws TorProcessException {
-
 		// check state
 		if (this.nodeState != NodeState.CONFIGURING) {
-			throw new IllegalStateException();
+			IllegalStateException e = new IllegalStateException();
+			this.logger.throwing(this.getClass().getName(),
+					"writeConfiguration", e);
+			throw e;
 		}
 
 		// write config file
@@ -581,159 +844,17 @@
 			}
 			bw.close();
 		} catch (IOException e) {
-			throw new TorProcessException("Could not write configuration!", e);
+			TorProcessException ex = new TorProcessException(
+					"Could not write configuration!", e);
+			this.logger.throwing(this.getClass().getName(),
+					"writeConfiguration", ex);
+			throw ex;
 		}
 
 		// change state
 		this.nodeState = NodeState.CONFIGURATION_WRITTEN;
-	}
 
-	/**
-	 * @see de.uniba.wiai.lspi.puppetor.ProxyNode#shutdown()
-	 */
-	public synchronized void shutdown() throws TorProcessException {
-
-		// check state
-		if (this.nodeState != NodeState.RUNNING) {
-			throw new IllegalStateException();
-		}
-
-		// we cannot simply kill the tor.exe process, because we have
-		// established a controller connection to it which would interpret a
-		// closed socket as failure and throw a RuntimeException
-		// TODO who cares?!
-		try {
-			this.conn.shutdownTor("SHUTDOWN");
-			this.conn.shutdownTor("SHUTDOWN");
-		} catch (IOException e) {
-			this.logger.log(Level.SEVERE,
-					"Could not send shutdown command to Tor process!", e);
-			throw new TorProcessException(
-					"Could not send shutdown command to Tor process!", e);
-		}
-
-		// change state
-		this.nodeState = NodeState.SHUT_DOWN;
+		// log exiting
+		this.logger.exiting(this.getClass().getName(), "writeConfiguration");
 	}
-
-	// /**
-	// * Flags that denotes whether certain events have been observed in the
-	// log.
-	// * In general, this requires logging to be done at least on notice level!
-	// */
-	// protected Set<Event> observedEvents;
-
-	// public synchronized boolean hasEventOccured(Event event) {
-	// return observedEvents.contains(event);
-	// }
-
-	public synchronized void hup() throws TorProcessException {
-
-		// check state
-		if (this.nodeState != NodeState.RUNNING) {
-			this.logger.log(Level.SEVERE,
-					"Cannot hup a process when it's not running!");
-			throw new IllegalStateException(
-					"Cannot hup a process when it's not running!");
-		}
-
-		// should we check whether conn is null?
-		if (this.conn == null) {
-			this.logger.log(Level.WARNING, "WARNING! conn is null!");
-		}
-		try {
-			// TODO sometimes, this throws a NullPointerException...
-			this.conn.signal("HUP");
-		} catch (IOException e) {
-			this.logger.log(Level.SEVERE,
-					"Could not send the command HUP to the Tor process!", e);
-			throw new TorProcessException(
-					"Could not send the command HUP to the Tor process!", e);
-		}
-	}
-
-	// public synchronized void addConfig(String newConfiguration) {
-	// if (this.nodeStatus != Status.CONFIGURING) {
-	// throw new IllegalStateException();
-	// }
-	// // TODO should we check the new config?!
-	// this.configuration.add(newConfiguration);
-	// }
-
-	// public String getConfiguration() {
-	// StringBuilder result = new StringBuilder("Node configuration: ");
-	// for (String next : this.configuration) {
-	// result.append(next + "\n");
-	// }
-	// return result.toString();
-	// }
-
-	/**
-	 * Adds a hidden service configuration to this node while the node is
-	 * running.
-	 * 
-	 * TODO this should be possible both, during configuration and when running
-	 * a network...
-	 */
-	public synchronized String addHiddenServiceUsingController(
-			String serviceName, int servicePort, int virtualPort) {
-		if (1 != 2)
-			throw new UnsupportedOperationException();
-		// TODO check state
-
-		// check params
-		if (serviceName == null || serviceName.length() == 0 || servicePort < 0
-				|| servicePort > 65535 || virtualPort < 0
-				|| virtualPort > 65535) {
-			throw new IllegalArgumentException();
-		}
-
-		// String serverName = server.getServerName();
-		// int serverPort = server.getServerPort();
-
-		// add hidden service using Tor controller
-		this.logger.log(Level.FINE,
-				"Adding hidden service using Tor controller.");
-
-		List<String> configs = new ArrayList<String>();
-		configs.add("HiddenServiceDir " + workingDir.getAbsolutePath() + "/"
-				+ serviceName);
-		configs.add("HiddenServicePort " + virtualPort + " 127.0.0.1:"
-				+ servicePort);
-		try {
-			conn.setConf(configs);
-		} catch (IOException e) {
-			throw new RuntimeException(
-					"IOException when trying to register a new "
-							+ "hidden service", e);
-		}
-		this.logger.log(Level.FINE,
-				"Hidden service successfully registered at Tor proxy.");
-
-		// 
-		File hiddenServiceFile = new File(workingDir.getAbsolutePath() + "\\"
-				+ serviceName + "\\hostname");
-		if (!hiddenServiceFile.exists()) {
-			throw new RuntimeException();
-		}
-		// read hostname from file
-		String address = null;
-		try {
-			// TODO use FileReader
-			FileInputStream fis = new FileInputStream(hiddenServiceFile);
-			BufferedInputStream bis = new BufferedInputStream(fis);
-			byte[] bytes = new byte[16];
-			bis.read(bytes);
-			address = new String(bytes) + ".onion";
-		} catch (IOException e) {
-			throw new RuntimeException(e);
-		}
-
-		return address;
-	}
-
-	public synchronized String getNodeName() {
-		return this.nodeName;
-	}
-
 }

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/RouterNodeImpl.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/RouterNodeImpl.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/RouterNodeImpl.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -1,8 +1,3 @@
-/*
- * NOTICE: This file is still work in progress. As you can see the Java
- * documentation is written partly in German and in English and logging and
- * documentation still need some work. Sorry for any inconvenience!  
- */
 package de.uniba.wiai.lspi.puppetor.impl;
 
 import java.io.BufferedReader;
@@ -19,34 +14,72 @@
 import de.uniba.wiai.lspi.puppetor.RouterNode;
 import de.uniba.wiai.lspi.puppetor.TorProcessException;
 
+/**
+ * Implementation of <code>RouterNode</code>.
+ * 
+ * @author kloesing
+ * 
+ */
 public class RouterNodeImpl extends ProxyNodeImpl implements RouterNode {
 
-	protected final String localIpAddress = "127.0.0.1";
-	
 	/**
-	 * OR port of this router.
+	 * Port on which the Tor node will be listening for directory requests from
+	 * other Tor nodes.
 	 */
-	protected int orPort;
+	protected int dirPort;
 
 	/**
-	 * Directory port of this router.
+	 * The fingerprint of this node that is determined as hash value of its
+	 * onion key.
 	 */
-	protected int dirPort;
+	protected String fingerprint;
 
 	/**
-	 * This node's fingerprint that is determined as hash value of this node's
-	 * onion routing key.
+	 * The IP address of local nodes (typically <code>localhost</code> or
+	 * <code>127.0.0.1</code>).
 	 */
-	protected String fingerprint;
+	protected final String localIpAddress = "127.0.0.1";
 
-	@Override
-	public String toString() {
-		return super.toString() + ", orPort=" + this.orPort + ", dirPort="
-				+ this.dirPort;
-	}
+	/**
+	 * Port on which the Tor node will be listening for onion requests by other
+	 * Tor nodes.
+	 */
+	protected int orPort;
 
-	public RouterNodeImpl(NetworkImpl network, String nodeName,
-			int controlPort, int socksPort, int orPort, int dirPort) {
+	/**
+	 * Creates a new <code>RouterNodeImpl</code> and adds it to the given
+	 * <code>network</code>, but does not yet write its configuration to disk
+	 * or start the corresponding Tor process.
+	 * 
+	 * @param network
+	 *            Network configuration to which this node belongs.
+	 * @param nodeName
+	 *            The name of the new node which may only consist of between 1
+	 *            and 19 alpha-numeric characters.
+	 * @param controlPort
+	 *            Port on which the Tor node will be listening for us as its
+	 *            controller. May not be negative or greater than 65535.
+	 * @param socksPort
+	 *            Port on which the Tor node will be listening for SOCKS
+	 *            connection requests. May not be negative or greater than
+	 *            65535.
+	 * @param orPort
+	 *            Port on which the Tor node will be listening for onion
+	 *            requests by other Tor nodes. May not be negative or greater
+	 *            than 65535.
+	 * @param dirPort
+	 *            Port on which the Tor node will be listening for directory
+	 *            requests from other Tor nodes. May not be negative or greater
+	 *            than 65535.
+	 * @throws IllegalArgumentException
+	 *             If at least one of the parameters is <code>null</code> or
+	 *             has an invalid value.
+	 */
+	RouterNodeImpl(NetworkImpl network, String nodeName, int controlPort,
+			int socksPort, int orPort, int dirPort) {
+
+		// create superclass instance; parameter checking is done in super
+		// constructor
 		super(network, nodeName, controlPort, socksPort);
 
 		// log entering
@@ -56,7 +89,10 @@
 
 		// check parameters
 		if (orPort < 0 || orPort > 65535 || dirPort < 0 || dirPort > 65535) {
-			throw new IllegalArgumentException();
+			IllegalArgumentException e = new IllegalArgumentException();
+			this.logger
+					.throwing(this.getClass().getName(), "RouterNodeImpl", e);
+			throw e;
 		}
 
 		// remember parameters
@@ -71,7 +107,7 @@
 		// all routers mirror the directory
 		this.configuration.add("DirPort " + dirPort);
 
-		// this node's address should be localhost and not guessed by Tor
+		// the address of this node should be localhost and not guessed by Tor
 		this.configuration.add("Address " + localIpAddress);
 
 		// the OR port may only be contacted locally
@@ -88,24 +124,26 @@
 
 		// bypass testing if we are reachable
 		this.configuration.add("AssumeReachable 1");
-		
+
 		// log exiting
 		this.logger.exiting(this.getClass().getName(), "RouterNodeImpl");
-
 	}
 
-	/**
-	 * @see de.uniba.wiai.lspi.puppetor.RouterNode#determineFingerprint()
-	 */
 	public synchronized String determineFingerprint()
 			throws TorProcessException {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "determineFingerprint");
+
+		// check if we can answer the request immediately
 		if (this.fingerprint != null) {
 
-			// we can answer the request immediately
+			// log exiting and return fingerprint
+			this.logger.exiting(this.getClass().getName(),
+					"determineFingerprint", this.fingerprint);
 			return this.fingerprint;
 		}
 
-
 		// write modified config file, including a DirServer option with
 		// false fingerprint; this is necessary, because otherwise Tor
 		// would not accept that this router node has a private IP
@@ -125,8 +163,11 @@
 			}
 			bw.close();
 		} catch (IOException e) {
-			throw new TorProcessException(
+			TorProcessException ex = new TorProcessException(
 					"Could not write temporary config file!", e);
+			this.logger.throwing(this.getClass().getName(),
+					"determineFingerprint", ex);
+			throw ex;
 		}
 
 		// start process with option --list-fingerprint
@@ -135,13 +176,15 @@
 		processBuilder.directory(this.workingDir);
 		processBuilder.redirectErrorStream(true);
 		Process tmpProcess = null;
-
 		try {
 			tmpProcess = processBuilder.start();
 		} catch (IOException e) {
-			throw new TorProcessException(
+			TorProcessException ex = new TorProcessException(
 					"Could not start Tor process temporarily with "
 							+ "--list-fingerprint option!", e);
+			this.logger.throwing(this.getClass().getName(),
+					"determineFingerprint", ex);
+			throw ex;
 		}
 
 		// start thread to parse output
@@ -150,14 +193,17 @@
 		Thread outputThread = new Thread(new Runnable() {
 			public void run() {
 				try {
-					// Read output from tor
+					// read output from tor
 					String line = null;
 					while ((line = br.readLine()) != null) {
 						// TODO discard output?
 						logger.log(Level.FINER, line);
 					}
 				} catch (IOException e) {
-					// TODO handle?
+					// TODO how to handle?
+					logger.log(Level.SEVERE,
+							"I/O exception while parsing output of temporary "
+									+ "Tor process!");
 				}
 			}
 		});
@@ -169,11 +215,12 @@
 		try {
 			tmpProcess.waitFor();
 		} catch (InterruptedException e) {
-			// TODO handle?
+			// TODO how to handle?
+			this.logger.log(Level.WARNING,
+					"Temporary Tor process was interrupted!", e);
 		}
 
 		// read fingerprint from file
-
 		File fingerprintFile = new File(this.workingDir.getAbsolutePath()
 				+ File.separator + "fingerprint");
 		try {
@@ -182,10 +229,22 @@
 			this.fingerprint = br2.readLine();
 			br2.close();
 		} catch (IOException e) {
-			throw new TorProcessException(
+			TorProcessException ex = new TorProcessException(
 					"Could not read fingerprint from file!", e);
+			this.logger.throwing(this.getClass().getName(),
+					"determineFingerprint", ex);
+			throw ex;
 		}
-		
+
+		// log exiting and return fingerprint
+		this.logger.exiting(this.getClass().getName(), "determineFingerprint",
+				this.fingerprint);
 		return this.fingerprint;
 	}
+
+	@Override
+	public String toString() {
+		return super.toString() + ", orPort=" + this.orPort + ", dirPort="
+				+ this.dirPort;
+	}
 }

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ServerApplicationImpl.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ServerApplicationImpl.java	2007-06-27 20:52:42 UTC (rev 10686)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ServerApplicationImpl.java	2007-06-27 22:09:47 UTC (rev 10687)
@@ -1,8 +1,3 @@
-/*
- * NOTICE: This file is still work in progress. As you can see the Java
- * documentation is written partly in German and in English and logging and
- * documentation still need some work. Sorry for any inconvenience!  
- */
 package de.uniba.wiai.lspi.puppetor.impl;
 
 import java.io.BufferedReader;
@@ -17,100 +12,109 @@
 import de.uniba.wiai.lspi.puppetor.Event;
 import de.uniba.wiai.lspi.puppetor.ServerApplication;
 
+/**
+ * Implementation of <code>ServerApplication</code>.
+ * 
+ * @author kloesing
+ */
 public class ServerApplicationImpl implements ServerApplication {
 
 	/**
-	 * logger für diesen server
+	 * Internal thread class that is used to process an incoming request.
 	 */
-	private Logger logger;
+	private class HandlerThread extends Thread {
 
-	private EventManagerImpl eventManager;
+		/**
+		 * Accepted socket on which the request came in.
+		 */
+		private Socket handleSocket = null;
 
-	private int serverPort;
+		/**
+		 * Creates a new thread to handle the request coming in on
+		 * <code>handleSocket</code>, but does not start handling it.
+		 * 
+		 * @param handleSocket
+		 *            Accepted socket on which the request came in.
+		 */
+		public HandlerThread(Socket handleSocket) {
 
-	/**
-	 * erzeugt neue server app innerhalb der jvm, fängt aber noch nicht an mit
-	 * listening.
-	 * 
-	 */
-	ServerApplicationImpl(NetworkImpl network, String serverApplicationName,
-			int serverPort) {
+			// log entering
+			logger.entering(this.getClass().getName(), "HandlerThread",
+					handleSocket);
 
-		// TODO make sure that name is loggable!!
+			// remember parameter
+			this.handleSocket = handleSocket;
 
-		// create logger
-		this.logger = Logger.getLogger("application." + serverApplicationName);
-
-		// log entering
-		this.logger.entering(this.getClass().getName(),
-				"ServerApplicationImpl", new Object[] { serverApplicationName,
-						serverPort });
-
-		// check parameters
-		if (serverApplicationName == null
-				|| serverApplicationName.length() == 0 || serverPort < 0
-				|| serverPort > 65535) {
-			throw new IllegalArgumentException();
+			// log exiting
+			logger.exiting(this.getClass().getName(), "HandlerThread");
 		}
 
-		// remember parameters
-		this.serverPort = serverPort;
+		@Override
+		public void run() {
 
-		// obtain reference on event manager
-		this.eventManager = network.getEventManagerImpl();
+			// log entering
+			logger.entering(this.getClass().getName(), "run");
 
-		// log exiting
-		this.logger.exiting(this.getClass().getName(), "ClientApplicationImpl");
-	}
+			try {
 
-	private Thread serverThread;
+				// wait for request (don't mind the content)
+				BufferedReader in = new BufferedReader(new InputStreamReader(
+						handleSocket.getInputStream()));
+				in.read();
 
-	public void stopListening() {
+				// send event to event manager
+				eventManager.observeEvent(ServerApplicationImpl.this,
+						Event.APPLICATION_REQUEST_RECEIVED);
 
-		// log entering
-		this.logger.entering(this.getClass().getName(), "stopListening");
+				// write response
+				PrintStream out = new PrintStream(handleSocket
+						.getOutputStream());
+				out.print("HTTP/1.0 200 OK\r\n");
 
-		// check if a request is running
-		if (this.serverThread == null) {
-			throw new IllegalStateException(
-					"We did not start listening before!");
-		}
+			} catch (IOException e) {
+				logger.log(Level.SEVERE,
+						"I/O exception while handling incoming request!");
+				// we can't do more, because nobody takes notice of this thread.
 
-		// log this event
-		this.logger.log(Level.FINE, "Shutting down server");
+				// log exiting
+				logger.exiting(this.getClass().getName(), "run");
+				return;
+				// TODO do we need more?
+			}
 
-		// interrupt thread
-		this.serverThread.interrupt();
+			// close socket
+			try {
+				handleSocket.close();
+			} catch (IOException e) {
+				logger
+						.log(Level.WARNING,
+								"I/O exception while closing socket!");
 
-		// log exiting
-		this.logger.exiting(this.getClass().getName(), "stopListening");
+				// log exiting
+				logger.exiting(this.getClass().getName(), "run");
+				return;
+			}
 
-	}
-
-	public void listen() {
-
-		// log entering
-		this.logger.entering(this.getClass().getName(), "listen");
-
-		// check if we are already listening
-		if (this.serverThread != null) {
-			throw new IllegalStateException("We are already listening!");
+			// log exiting
+			logger.exiting(this.getClass().getName(), "run");
 		}
-
-		// create a thread that listens in the background
-		this.serverThread = new ListenThread();
-		this.serverThread.setName("Reply Thread");
-		this.serverThread.setDaemon(true);
-		this.serverThread.start();
-
-		// log exiting
-		this.logger.exiting(this.getClass().getName(), "listen");
 	}
 
+	/**
+	 * Internal thread class that is used to listen for requests.
+	 */
 	private class ListenThread extends Thread {
 
+		/**
+		 * Flag to remember whether this thread listens for requests at the
+		 * moment (<code>true</code>), or has been stopped (<code>false</code>).
+		 */
 		private boolean connected;
 
+		/**
+		 * Creates a new thread to listen for requests, but does not start
+		 * listening, yet.
+		 */
 		ListenThread() {
 
 			// log entering
@@ -123,23 +127,6 @@
 			logger.exiting(this.getClass().getName(), "ListenThread");
 		}
 
-		/**
-		 * stoppt listening
-		 * 
-		 */
-		public void stopListening() {
-
-			// log entering
-			logger.entering(this.getClass().getName(), "stopListening");
-
-			// change connected state to false and interrupt thread
-			this.connected = false;
-			this.interrupt();
-
-			// log exiting
-			logger.exiting(this.getClass().getName(), "stopListening");
-		}
-
 		@Override
 		public void run() {
 
@@ -148,75 +135,196 @@
 
 			try {
 
+				// create server socket
 				ServerSocket serverSocket = null;
-
 				try {
 					serverSocket = new ServerSocket(serverPort);
 				} catch (IOException ioe) {
-					logger.log(Level.WARNING, "Can't open server socket on port "
-							+ serverPort + "!");
+					logger.log(Level.SEVERE,
+							"Can't open server socket on port " + serverPort
+									+ "!");
+
+					// log exiting
+					logger.exiting(this.getClass().getName(), "run");
+					return;
 				}
-				logger.log(Level.FINE, "Listening on port " + serverPort + "...");
+
+				// as long as we are connected, accept incoming requests
+				logger.log(Level.FINE, "Listening on port " + serverPort
+						+ "...");
 				while (connected) {
+					Socket incomingConnection = null;
 					try {
-						Socket incomingConnection = serverSocket.accept();
-						HandlerThread handler = new HandlerThread(
-								incomingConnection);
-						new Thread(handler).start();
+						incomingConnection = serverSocket.accept();
 					} catch (Exception e) {
+						logger
+								.log(
+										Level.SEVERE,
+										"Exception while accepting socket requests! Stopping listening!",
+										e);
+						break;
 					}
+					new HandlerThread(incomingConnection).start();
 				}
 
 			} catch (Exception e) {
 
 				// log that we have been interrupted
 				logger.log(Level.WARNING, "Server has been interrupted!", e);
-
-				// log exiting
-				logger.exiting(this.getClass().getName(), "run");
 			}
 
+			// mark as disconnected
+			this.connected = false;
+
+			// log exiting
+			logger.exiting(this.getClass().getName(), "run");
 		}
 
+		/**
+		 * Stops listening on server socket.
+		 */
+		public void stopListening() {
+
+			// log entering
+			logger.entering(this.getClass().getName(), "stopListening");
+
+			// change connected state to false and interrupt thread
+			this.connected = false;
+			this.interrupt();
+
+			// log exiting
+			logger.exiting(this.getClass().getName(), "stopListening");
+		}
 	}
 
-	private class HandlerThread implements Runnable {
+	/**
+	 * Event manager to which all events concerning this server application are
+	 * notified.
+	 */
+	private EventManagerImpl eventManager;
 
-		private Socket handleSocket = null;
+	/**
+	 * Logger for this server.
+	 */
+	private Logger logger;
 
-		public HandlerThread(Socket requestSocket) {
-			handleSocket = requestSocket;
+	/**
+	 * Name of this server application that is used as logger name of this node.
+	 */
+	private String serverApplicationName;
+
+	/**
+	 * Port on which this server will listen for incoming requests.
+	 */
+	private int serverPort;
+
+	/**
+	 * Thread that listens for requests in the background.
+	 */
+	private Thread serverThread;
+
+	/**
+	 * Creates a new HTTP server application within this JVM, but does not yet
+	 * listen for incoming requests.
+	 * 
+	 * @param network
+	 *            Network to which this HTTP server belongs; at the moment this
+	 *            is only used to determine the event manager instance.
+	 * @param serverApplicationName
+	 *            Name of this server that is used as part of the logger name.
+	 * @param serverPort
+	 *            Port on which this server will listen for incoming requests.
+	 * @throws IllegalArgumentException
+	 *             If at least one of the parameters is <code>null</code> or
+	 *             has an invalid value.
+	 */
+	ServerApplicationImpl(NetworkImpl network, String serverApplicationName,
+			int serverPort) {
+
+		// check if serverApplicationName can be used as logger name
+		if (serverApplicationName == null
+				|| serverApplicationName.length() == 0) {
+			throw new IllegalArgumentException(
+					"Invalid serverApplicationName: " + serverApplicationName);
 		}
 
-		public void run() {
+		// create logger
+		this.logger = Logger.getLogger("application." + serverApplicationName);
 
-			try {
+		// log entering
+		this.logger.entering(this.getClass().getName(),
+				"ServerApplicationImpl", new Object[] { network,
+						serverApplicationName, serverPort });
 
-				// wait for request (don't mind content)
-				BufferedReader in = new BufferedReader(new InputStreamReader(
-						handleSocket.getInputStream()));
-				in.read();
+		// check parameters
+		if (network == null || serverPort < 0 || serverPort > 65535) {
+			IllegalArgumentException e = new IllegalArgumentException();
+			this.logger.throwing(this.getClass().getName(),
+					"ServerApplicationImpl", e);
+			throw e;
+		}
 
-				// send event to event manager
-				eventManager.observeEvent(ServerApplicationImpl.this,
-						Event.APPLICATION_REQUEST_RECEIVED);
+		// remember parameters
+		this.serverApplicationName = serverApplicationName;
+		this.serverPort = serverPort;
 
-				// write response
-				PrintStream out = new PrintStream(handleSocket
-						.getOutputStream());
-				out.print("HTTP/1.0 200 OK\r\n");
+		// obtain reference on event manager
+		this.eventManager = network.getEventManagerImpl();
 
-			} catch (Exception e) {
-				e.printStackTrace();
-			}
+		// log exiting
+		this.logger.exiting(this.getClass().getName(), "ServerApplicationImpl");
+	}
 
-			try {
-				// handleSocket.getInputStream().close();
-				// handleSocket.getOutputStream().flush();
-				// handleSocket.getOutputStream().close();
-				handleSocket.close();
-			} catch (Exception e) {
-			}
+	public synchronized void listen() {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "listen");
+
+		// check if we are already listening
+		if (this.serverThread != null) {
+			IllegalStateException e = new IllegalStateException(
+					"We are already listening!");
+			this.logger.throwing(this.getClass().getName(), "listen", e);
+			throw e;
 		}
+
+		// create a thread that listens in the background
+		this.serverThread = new ListenThread();
+		this.serverThread.setName("Reply Thread");
+		this.serverThread.setDaemon(true);
+		this.serverThread.start();
+
+		// log exiting
+		this.logger.exiting(this.getClass().getName(), "listen");
 	}
+
+	public synchronized void stopListening() {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "stopListening");
+
+		// check if a request is running
+		if (this.serverThread == null) {
+			IllegalStateException e = new IllegalStateException(
+					"We did not start listening before!");
+			this.logger.throwing(this.getClass().getName(), "stopListening", e);
+			throw e;
+		}
+
+		// log this event
+		this.logger.log(Level.FINE, "Shutting down server");
+
+		// interrupt thread
+		this.serverThread.interrupt();
+
+		// log exiting
+		this.logger.exiting(this.getClass().getName(), "stopListening");
+	}
+
+	@Override
+	public String toString() {
+		return this.getClass().getSimpleName() + ": serverApplicationName=\""
+				+ this.serverApplicationName + "\", serverPort="
+				+ this.serverPort;
+	}
 }